如何在SWIFT中创建Range? [英] How to create range in Swift?

查看:50
本文介绍了如何在SWIFT中创建Range?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

NSRange range;

那么如何在SWIFT中创建Range?

推荐答案

针对SWIFT 4更新

SWIFT范围比NSRange更复杂,在SWIFT 3中也不会变得更容易。如果您想尝试了解其中一些复杂性背后的原因,请阅读thisthis。我将向您演示如何创建它们以及您何时可以使用它们。

封闭范围:a...b

thisrange operator创建同时包括a元素b的SWIFT范围,即使b是某个类型的最大可能值(如Int.max)。有两种不同类型的闭合范围:ClosedRangeCountableClosedRange

1.ClosedRange

SWIFT中所有范围的要素具有可比性(即,它们符合可比协议)。这允许您从集合访问范围中的元素。下面是一个例子:

let myRange: ClosedRange = 1...3

let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c", "d"]
然而,aClosedRange是不可数的(即,它不符合序列协议)。这意味着您不能使用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,但不包括元素b。与上面一样,有两种不同类型的半开范围:RangeCountableRange

1.Range

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

let myRange: Range = 1..<3

let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c"]
但是,您不能在Range上迭代,因为它只是可比较的,不是可跨越的。

2.CountableRange

ACountableRange允许迭代。

let myRange: CountableRange = 1..<3

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

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

NSRange

您仍然可以(必须)在SWIFT中使用NSRange(例如,在制作attributed strings时),因此了解如何制作NSRange会很有帮助。

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
您可以看到这里的索引类型是Int。但是,这不适用于String,因为字符串是由字符组成的,并不是所有字符的大小都相同。(有关更多信息,请阅读this。)例如,像😀这样的表情符号比字母"b"占用更多的空间。

NSRange问题

尝试使用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"的意外结果。

SWIFT解决方案

因此,对于SWIFT字符串,您使用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中,事情做了一些简化。只要可以推断范围的起点或终点,您就可以将其停用。

Int

您可以使用单边整数范围迭代集合。以下是documentation中的一些示例。

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

另请参阅:

备注

  • 您不能使用在不同字符串上使用一个字符串创建的区域。
  • 如你所见,字符串范围是SWIFT的一个难题,但它们确实使它有可能更好地处理emoji和其他Unicode标量。

进一步研究

这篇关于如何在SWIFT中创建Range?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆