如何在Swift中创建范围?

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

NSRange range;

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

回答:

为Swift 4更新

Swift范围比复杂NSRange,并且在Swift

3中并没有那么简单。如果您想尝试了解这种复杂性背后的原因,请阅读this和this。我将仅向您展示如何创建它们以及何时使用它们。

封闭范围: a...b

此范围运算符创建一个Swift范围,其中既包含element

a 包含element

b,即使它b是类型(如Int.max)的最大可能值。封闭范围有两种不同类型:ClosedRangeCountableClosedRange

1。 ClosedRange

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

let myRange: ClosedRange = 1...3

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

myArray[myRange] // ["b", "c", "d"]

但是,aClosedRange是不可数的(即,它不符合Sequence协议)。这意味着您不能使用循环来遍历元素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

此范围运算符包括element,a但 _不_包括elementb。像上面一样,有两种不同类型的半开范围:RangeCountableRange

1。 Range

与一样ClosedRange,您可以使用来访问集合的元素Range。例:

let myRange: Range = 1..<3

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

myArray[myRange] // ["b", "c"]

同样,您不能对a进行迭代,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中使用(例如,在制作属性字符串时),因此了解如何制作一个字符串很有帮助。

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

请注意,这是位置和 长度 ,而不是开始索引和结束索引。此处的示例在含义上与Swift范围相似3..<5。但是,由于类型不同,因此不能互换。

带字符串的范围

.....<范围内经营者创建范围的简便方法。例如:

let myRange = 1..<3

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

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

您可以看到此处的索引类型为IntString但是,这不起作用,因为字符串是由字符组成的,并且并非所有字符的大小都相同。(有关更多信息,请阅读此内容。)例如????之类的表情符号比字母“

b”占用更多的空间。

尝试NSRangeNSString表情符号一起进行实验,您会明白我的意思的。头痛。

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”的意外结果。

正因为如此,随着斯威夫特字符串使用Range<String.Index>,不是Range<Int>。字符串索引是根据特定的字符串计算得出的,因此它知道是否存在任何表情符号或扩展的字形簇。

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......b..<b

在Swift 4中,事情做了一些简化。只要可以推断范围的起点或终点,就可以将其关闭。

您可以使用单面整数范围对集合进行迭代。以下是文档中的一些示例。

// 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...

这也适用于字符串范围。如果要在一端str.startIndexstr.endIndex另一端建立范围,则可以不设置范围。编译器将进行推断。

给定

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范围在Swift中很麻烦,但确实可以更好地处理表情符号和其他Unicode标量。

进一步研究

  • 字符串范围示例
  • 范围运算符文档
  • 字符串和字符文档

以上是 如何在Swift中创建范围? 的全部内容, 来源链接: utcz.com/qa/403782.html

回到顶部