swift数组简介1

83 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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]