一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情。
可变性
- 数组和标准库中的所有集合类型一样,是具有值语义的
var x = [1,2,3]
var y = x
y.append(4)
y // [1, 2, 3, 4]
x // [1, 2, 3]
想要改变一个数组,必须使用NSMutableArray,
但是NSArray的引用特性并不能保证这个数组不会被改变
let a = NSMutableArray(array: ["1", "2", "3"])
let b = a
a.insert("4", at: 3)
print(b)
(
1,
2,
3,
4
)
需要进行复制, 因为a声明是可变的
let c = NSMutableArray(array: ["1", "2", "3"])
let d = c.copy() as! NSArray
c.insert("4", at: 3)
print(d)
(
1,
2,
3
)
“在 Swift 中,数组只有一种统一的类型,可以通过在声明时使用 var 而非 let 来将数组定义为可变的。当你使用 let 声明第二个数组,并将第一个数组赋值给它时,可以保证这个新的数组是不会改变的,因为这里没有共用的引用。”
写实复制: 创建如此多的copy,会造成性能上的问题。所以引入了“写时复制”的技术。保证能够在必要的时候对数据进行复制。
y在append之前x, y共享内部的存储
索引
Swift不鼓励去做索引计算,因为这样做可能会引起潜在bug.无效的下标会造成可控的崩溃, 数组没有可选值选项。
- 迭代数组 for x in array
- 迭代除了第一个数组 for x in array.dropFirst()
- 迭代除了最后5个数组 for x in array.dropLast(5)
- 列举元素和对应的下标 for(num, element) in array.enumerated
- 寻找指定元素 if let index = array.firstIndex(where: { $0=="1" })
- 数组元素变形array.map { return $0 + "1"}
- 筛选出符合条件的元素array.filter { $0=="1" }
下面操作略有不同
- array.first(array.last 同理) 相当于
isEmpty ? nil : array[0]
-
removeLast & popLast & dropLast
- removeLast空数组将造成崩溃
- popLast删除空数组时会返回nil,删除元素时,会返回该元素
- dropLast删除空数组时会返回nil,删除元素时,会返回剩余元素数组
变形
Map
var squared: [Int] = []
for fib in fibs {
squared.append(fib * fib)
}
squared // [0, 1, 1, 4, 9, 25]
map完成的操作
var squared: [Int] = []
for fib in fibs {
squared.append(fib * fib)
}
squared // [0, 1, 1, 4, 9, 25]
优势
- 长度短,代表错误少, 清晰
- map相当于一个信号
- map返回的数组用let声明
Map函数内部可能实现方式
extension Array {
func map<T>(_ transform: (Element)->T) -> [T] {
var result: [T] = []
result.reserveCapacity(count)
for x in self {
result.append(transform(x))
}
return result
}
}
Element是数组中包含元素类型的占位符,T是元素转换后的类型的占位符
实际上这个函数签名应该是
func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]