如何在 Swift 中创建范围?

2023-12-28

在 Objective-c 中,我们使用 NSRange 创建范围

NSRange range;

那么如何在 Swift 中创建范围呢?


更新为 Swift 4

Swift 范围比NSRange,并且它们在 Swift 3 中并没有变得更容易。如果你想尝试理解这种复杂性背后的原因,请阅读this https://oleb.net/blog/2016/09/swift-3-ranges/ and this https://github.com/apple/swift-evolution/blob/master/proposals/0065-collections-move-indices.md。我将向您展示如何创建它们以及何时可以使用它们。

封闭范围:a...b

This 范围运算符 https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html创建一个 Swift 范围,其中包含两个元素a and元素b, 即使b是类型的最大可能值(例如Int.max)。有两种不同类型的封闭范围:ClosedRange and CountableClosedRange.

1. ClosedRange

Swift 中所有范围的元素都是可比较的(即它们符合 Comparable 协议)。这允许您访问集合中范围内的元素。这是一个例子:

let myRange: ClosedRange = 1...3

let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c", "d"]

然而,一个ClosedRange不可数(即不符合Sequence协议)。这意味着您不能使用 a 迭代元素for环形。为此,您需要CountableClosedRange.

2. CountableClosedRange

这与上一个类似,只是现在范围也可以迭代。

let myRange: CountableClosedRange = 1...3

let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c", "d"]

for index in myRange {
    print(myArray[index])
}

半开范围:a..<b

该范围运算符包括元素a but not元素b。与上面一样,有两种不同类型的半开范围:Range and CountableRange.

1. Range

As with ClosedRange,您可以使用以下方式访问集合的元素Range。例子:

let myRange: Range = 1..<3

let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c"]

但同样,你不能迭代Range因为它只能比较,不能跨越。

2. CountableRange

A CountableRange允许迭代。

let myRange: CountableRange = 1..<3

let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c"]

for index in myRange {
    print(myArray[index])
}

NSRange

您仍然可以(必须)使用NSRange有时在 Swift 中(当制作属性字符串 https://stackoverflow.com/a/32269975/3681880,例如),因此了解如何制作一个是有帮助的。

let myNSRange = NSRange(location: 3, length: 2)

请注意,这是位置和length,不是开始索引和结束索引。这里的例子与 Swift range 的含义类似3..<5。但由于类型不同,因此不能互换。

带字符串的范围

The ... and ..<范围运算符是创建范围的简写方式。例如:

let myRange = 1..<3

创建相同范围的长手方法是

let myRange = CountableRange<Int>(uncheckedBounds: (lower: 1, upper: 3)) // 1..<3

可以看到这里的索引类型是Int。这不适合String但是,因为字符串是由字符组成的,并且并非所有字符的大小都相同。 (读this https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html了解更多信息。)例如,像 ???? 这样的表情符号比字母“b”占用更多空间。

NSRange 的问题

尝试尝试NSRange and an NSString加上表情符号,你就会明白我的意思了。头痛。

let myNSRange = NSRange(location: 1, length: 3)

let myNSString: NSString = "abcde"
myNSString.substring(with: myNSRange) // "bcd"

let myNSString2: NSString = "a????cde"
myNSString2.substring(with: myNSRange) // "????c"    Where is the "d"!?

笑脸需要两个 UTF-16 代码单元来存储,因此它给出了不包含“d”的意外结果。

迅捷解决方案

因此,对于 Swift Strings,您可以使用Range<String.Index>, not Range<Int>。字符串索引是根据特定字符串计算的,以便它知道是否存在任何表情符号或扩展字素簇。

Example

var myString = "abcde"
let start = myString.index(myString.startIndex, offsetBy: 1)
let end = myString.index(myString.startIndex, offsetBy: 4)
let myRange = start..<end
myString[myRange] // "bcd"

myString = "a????cde"
let start2 = myString.index(myString.startIndex, offsetBy: 1)
let end2 = myString.index(myString.startIndex, offsetBy: 4)
let myRange2 = start2..<end2
myString[myRange2] // "????cd"

单边范围:a... and ...b and ..<b

在 Swift 4 中,事情被简化了一些。只要可以推断出范围的起点或终点,您就可以将其保留。

Int

您可以使用单边整数范围来迭代集合。以下是一些来自文档 https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html.

// iterate from index 2 to the end of the array
for name in names[2...] {
    print(name)
}

// iterate from the beginning of the array to index 2
for name in names[...2] {
    print(name)
}

// iterate from the beginning of the array up to but not including index 2
for name in names[..<2] {
    print(name)
}

// the range from negative infinity to 5. You can't iterate forward
// over this because the starting point in unknown.
let range = ...5
range.contains(7)   // false
range.contains(4)   // true
range.contains(-1)  // true

// You can iterate over this but it will be an infinate loop 
// so you have to break out at some point.
let range = 5...

String

这也适用于字符串范围。如果您正在制作一个范围str.startIndex or str.endIndex一方面,您可以将其保留。编译器会推断它。

Given

var str = "Hello, playground"
let index = str.index(str.startIndex, offsetBy: 5)

let myRange = ..<index    // Hello

您可以使用以下命令从索引转到 str.endIndex...

var str = "Hello, playground"
let index = str.index(str.endIndex, offsetBy: -10)
let myRange = index...        // playground

也可以看看:

  • String.Index 在 Swift 中如何工作 https://stackoverflow.com/a/39676940/3681880
  • String 子字符串在 Swift 中如何工作 https://stackoverflow.com/a/39677331/3681880

Notes

  • 您不能在不同的字符串上使用通过一个字符串创建的范围。
  • 正如您所看到的,字符串范围在 Swift 中是一个难题,但它们确实可以更好地处理表情符号和其他 Unicode 标量。

进一步研究

  • 字符串范围示例 http://www.dotnetperls.com/substring-swift
  • 范围运算符文档 https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html
  • 字符串和字符文档 https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Swift 中创建范围? 的相关文章

随机推荐

  • MySQL 的 C++ 连接器

    EDITED 我的问题是这篇文章底部的错误 这是我的附加包含目录 C Program Files boost C Program Files MySQL MySQL Connector C 1 1 3 include C Program F
  • 对未使用的变量使用占位符时出现 MatchError

    使用 Scala 2 13 x 我得到scala MatchError null当我对未使用的变量使用占位符时 scala gt object Test val Any null object Test scala gt Test scal
  • 如何在 Linux 中获取 .Net 文件的 AssemblyVersion

    有没有办法在不使用 mono 的情况下在 Linux 中获取 Net 可执行文件的 AssemblyVersion 我想要的是一个脚本或命令 可以让我在 Linux 机器上获取 AssemblyVersion 我试过 strings fil
  • 我的 NgRx 效果不起作用,没有任何反应

    我的 NgRx 效果有问题 该应用程序正确地添加到商店 不幸的是我的请求效果没有执行 即在启动添加新车时 将其添加到商店 仅此而已 问题是我的效果没有控制台日志 没有由于错误的网址而导致的 http 错误 什么也没有 我的应用程序代码 Re
  • Android textview 用作标签和值

    我想将两个文本视图分组为一个组并使用标签和值 android中是否有任何组件可以将两个textview分组 在android布局中如何实现呢 您可以使用
  • 节点拒绝应用样式,因为其 MIME 类型('text/html')不是受支持的样式表 MIME

    我要提供静态服务index html with main css使用此节点服务器 该serve js var express require express var cors require cors var app express var
  • RuntimeError:只能计算浮点类型的平均值。取而代之的是字节。对于平均值 += images_data.mean(2).sum(0)

    我有以下代码 Device configuration device torch device cuda 0 if torch cuda is available else cpu seed 42 np random seed seed t
  • 显示所有 jinja 对象属性

    有没有办法在 jinja 模板中显示给定对象的所有属性的名称 内容 功能 这将使调试未按预期运行的模板变得更加容易 我正在使用以下方式建立一个网站hyde框架 这会非常方便 因为我仍在学习 jinja 和 hyde 的复杂性 最初 我以为使
  • c 中的快速模 10

    我正在寻找一种快速的模 10 算法 因为我需要加速我的程序 该程序在循环中执行许多模运算 我已经结帐了这一页 http cc davelozinski com c sharp use the modulus operator or alte
  • 如何在Flutter中仅选择单选按钮的一组值?

    我正在使用 Flutter Dart SQLite 开发测验应用程序 在这里 我使用 RadioListTile 来实现单选按钮功能 我将文本值从数组传递到此StatefulWidget 这是我正在使用的代码 import package
  • LinkedHashMap EntrySet 的顺序未保留在流中(Android)

    我正在为注册屏幕创建一个非常简单的表单验证实用程序 并且我遇到了一些关于以下方面的意外行为LinkedHashMap以及从其创建的流entrySet 我将验证结果存储在LinkedHashMap 语句顺序如下 Map
  • 我想在我的项目中创建 django 弹出表单 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我在 django 中创建了费用管理系统 问题是我使用简单的表单 对于每个表单 用户必须导航到单独的页面 我想在 django 中创建
  • React:axios网络错误

    这是我第一次使用axios 遇到了一个错误 axios get http someurl com page1 param1 1 param2 param2 id then function response alert catch func
  • 数据表动态隐藏/显示列太慢

    我的目标是使用数据表 JQuery 插件动态显示 隐藏列 当我有大约 500 行时 需要很长时间才能完成 我正在使用新的 Datatables API 1 10 0 oats detailed view button click funct
  • 寻找多个多边形的共同轮廓

    我试图找到一种在多个多边形之间绘制公共轮廓的算法 我的意思就像这张照片上的那样 我们有两个矩形 在我的例子中 它们不是矩形 而是大多数角度为直角的多边形 我正在寻找共同的轮廓 例如图像第二部分上的红色路径 我认为最大的问题是找到新的点 我在
  • 如何在 Visual Studio 2008 C++ 中链接 .lib

    我发现将 lib 文件正确链接到我的 C Win32 控制台应用程序确实很困难 这是我的问题 正如这篇 MSDN 文章中一样 我开发了一个 MathFuncsLib lib 文件 http msdn microsoft com en us
  • 使用计算字段正确显示数据透视表中的总计

    我有一个 Excel 数据透视表 看起来像 Date Sum of DURATION Capped Daily Total 03 Jan 9 5 8 0 04 Jan 6 0 6 0 05 Jan 10 5 8 0 06 Jan 4 5 4
  • Python selenium“about:blank&utm_content=firstrun”错误

    我一直在努力弄清楚我的代码发生了什么 但我无能为力 每当我运行我的程序时 我都会收到下图中的错误 我正在使用 python 3 4 4 和 selenium 的最新版本 Windows 10 from selenium import web
  • Django 按日期排序(日)

    我想先按天排序模型 然后按分数排序 这意味着我希望看到每天得分最高的文章 class Article models Model date modified models DateTimeField blank True null True
  • 如何在 Swift 中创建范围?

    在 Objective c 中 我们使用 NSRange 创建范围 NSRange range 那么如何在 Swift 中创建范围呢 更新为 Swift 4 Swift 范围比NSRange 并且它们在 Swift 3 中并没有变得更容易