0%

Swift数组截取

数组截取的一些方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
let arr = [1, 2, 3, 4, 5]
//startIndex:0, endIndex:5
print("startIndex:\(arr.startIndex), endIndex:\(arr.endIndex)")

let slice1 = arr.dropFirst(2)
//startIndex:2, endIndex:5
print("startIndex:\(slice1.startIndex), endIndex:\(slice1.endIndex)")

let slice2 = arr.dropFirst().dropLast()
//startIndex:1, endIndex:4
print("startIndex:\(slice2.startIndex), endIndex:\(slice2.endIndex)")

let rs = arr.dropFirst().prefix(upTo: 3)
print(rs) //[2, 3]

let rs1 = arr.dropFirst().prefix(3)
print(rs1) //[2, 3, 4]

let fib = [1, 1, 2, 3, 5, 8, 13, 21]
let slfib = fib[1...5]
//startIndex:1, endIndex:6
print("startIndex:\(slfib.startIndex), endIndex:\(slfib.endIndex)")
print(slfib) //[1, 2, 3, 5, 8]

/**
prefix(upTo end: Int)
表示从集合的索引startIndex开始截取到索引n之间的元素,不包含索引n元素。n取值范围:[startIndex, endIndex],传startIndex则返回空数组,传endIndex则返回整个数组。
*/
let prefixArr0 = arr.prefix(upTo: arr.startIndex)
print(prefixArr0) //[]

let prefixArr = arr.prefix(upTo: 3)
print(prefixArr) //[1, 2, 3]

let prefixArr1 = arr.prefix(upTo: arr.endIndex)
print(prefixArr1) //[1, 2, 3, 4, 5]

let prefixArr2 = slfib.prefix(upTo: 3) //根据上面说明这里只能取[1, 6],取0会崩溃
print(prefixArr2) //[1, 2]

//prefix(_ maxLength: Int),表示截取集合前n个元素,n取值范围:n>=0,当n = 0时,返回空数组;当n>数组个数时,则返回全部。
let preArr2 = arr.prefix(2)
print(preArr2) //[1, 2]

/**
prefix(through position: Int)
表示从集合的索引startIndex开始截取到索引n之间的元素,包含索引n元素。n取值范围:[startIndex, endIndex)。
*/
let preArr3 = arr.prefix(through: 4)
print(preArr3) //[1, 2, 3, 4, 5]

//suffix(from start: Int):从集合的索引n元素开始截取到末尾,包含索引n元素,n取值范围:[startIndex, endIndex],当n为endIndex时,结果为空数组。
let suffixArr0 = arr.suffix(from: arr.startIndex)
print(suffixArr0) //[1, 2, 3, 4, 5]

let suffixArr00 = arr.suffix(from: arr.endIndex)
print(suffixArr00) //[]

let suffixArr = arr.suffix(from: 3)
print(suffixArr) //[4, 5]

let suffixArr2 = slfib.suffix(from: 3) //这里参数也不能取0,因为startIndex==1。
print(suffixArr2) //[3, 5, 8]

//suffix(_ maxLength: Int):截取集合的最后n个元素,n取值范围:n>=0,当n = 0时,返回空数组;当n>数组元素个数时,则返回全部。
let suffixArr1 = arr.suffix(0)
print(suffixArr1) //[]

//使用range时,参数取值范围为[0, 数组个数],且start<=end。当start 或 end 等于count时,右边只能用"<"或省略end了。不能等于,否则越界了。
let rangeArr = arr[3...3]
print(rangeArr) //[4]

let rangeArr1 = arr[2..<4]
print(rangeArr1) //[3, 4]

let rangeArr2 = arr[2...]
print(rangeArr2) //[3, 4, 5]

let rangeArr3 = arr[..<3]
print(rangeArr3) //[1, 2, 3]

let rangeArr4 = arr[5..<5]
print(rangeArr4) //[]

let rangeArr5 = arr[5...]
print(rangeArr5) //[]

//从头部开始删除n个元素,当n>数组元素个数时表示删除全部,结果返回空数组。
let dropFirstArr = arr.dropFirst(3)
print(dropFirstArr) //[4, 5]

//从尾部开始删除n个元素,当n>数组元素个数时表示删除全部,结果返回空数组。
let dropLastArr = arr.dropLast(3)
print(dropLastArr) //[1, 2]

上述操作之后得到的都是数组切片类型,而不是数组类型。这里简单介绍一下ArraySlice 类型,因为上面有些方法是跟索引相关的,比如方法prefix(upTo end: Int),而ArraySlice 类型的startIndex并不总是从0开始,所以得到的结果可能出乎你的预料。

ArraySlice 类型官方文档:

The ArraySlice type makes it fast and efficient for you to perform operations on sections of a larger array. Instead of copying over the elements of a slice to new storage, an ArraySliceinstance presents a view onto the storage of a larger array. And because ArraySlice presents the same interface as Array, you can generally perform the same operations on a slice as you could on the original array.

Unlike Array and ContiguousArray, the starting index for an ArraySlice instance isn’t always zero. Slices maintain the same indices of the larger array for the same elements, so the starting index of a slice depends on how it was created, letting you perform index-based operations on either a full array or a slice.

ArraySliceArray, ContiguousArray, or ArraySlice 实例的一个切片。但是它并不会将切片中的元素拷贝到一个新的存储空间,而是依然指向原始数组。

注意:endIndex始终指向集合最后一个元素的后一个位置。系统的很多方法涉及到索引时都会跟startIndex和endIndex相关。而不是0和数组个数。

ArraySlice的startIndex并不总是从0开始,而是取决于它的创建方式。下面的例子中可以看到slice1的startIndex是2而不是0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let arr = [1, 2, 3, 4, 5]
//startIndex:0, endIndex:5
print("startIndex:\(arr.startIndex), endIndex:\(arr.endIndex)")

let slice1 = arr.dropFirst(2)
//startIndex:2, endIndex:5
print("startIndex:\(slice1.startIndex), endIndex:\(slice1.endIndex)")

let slice2 = arr.dropFirst().dropLast()
//startIndex:1, endIndex:4
print("startIndex:\(slice2.startIndex), endIndex:\(slice2.endIndex)")

let rs = arr.dropFirst().prefix(upTo: 3)
print(rs) //[2, 3]

let rs1 = arr.dropFirst().prefix(3)
print(rs1) //[2, 3, 4]

接下来解释一下arr.dropFirst().prefix(upTo: 3)的结果为什么是[2, 3],而不是[2, 3, 4]。

首先arr.dropFirst()将得到一个切片[2, 3, 4, 5],它的startIndex为1,endIndex为5。prefix(upTo: 3)表示从startIndex开始取到索引为3的元素(不包括),而切片的startIndex为1,所以这里只会取索引为1,2的元素,所以结果为[2, 3]。而prefix(3)表示取前3个,所以结果为[2, 3, 4]。

参考

ArraySlice

WWDC 2018:在Swift中如何高效地使用集合

觉得文章有帮助可以打赏一下哦!