SwiftNote-Array

285 阅读9分钟

创建数组

  • 字面量创建: 使用 [] 括起来,里面的每个元素使用逗号分割。

    let array = [1, 2, 3, 4]
    
  • 字面量创建空数组必须指明数组的类型。

    let array:[String] = []
    
  • 初始化器创建数组

    • [类型]()

      var array = [String]()
      
    • Array<类型>()

      var array = Array<String>()
      
    • init(repeating repeatedValue: Element, count: Int)

    • init(arrayLiteral element: Element)

      let fiveZs = Array(repeating: "Z", count: 5)
      print(fiveZs)
      // ["Z", "Z", "Z", "Z", "Z"]
      
    • init<S>(_ elements: S) where S: Sequence, Self.Element == S.Element

    • init(from decoder: Decoder) throws

      let numbers = [Int](0..<7)
      print(numbers)
      // [0, 1, 2, 3, 4, 5, 6]
      let person = ["zhangsan": 27, "lisi": 30, "wangwu": 18]
      let names = [String](person.keys)
      print(names)
      // ["lisi", "zhangsan", "wangwu"]
      

遍历数组

  • for-in

    let numbers = [1, 2, 3]
    for i in numbers {
        print(i)
    }
    // 控制台输出:1,2,3
    
  • forEach

    • 无法使用 break 或 continue 跳出或者跳过循环
    • 使用 return 只能退出当前一次的循环执行体,不能结束整个循环
    let numbers = [Int](2...7)
    numbers.forEach { (num) in
        print(num * 10)
    }
    // 控制台输出:20,30,40, 50, 60, 70
    
  • enumerated(): 得到索引和值

    let numbers = [Int](2...4)
    for (index, num) in numbers.enumerated() {
        print("the index is \(index)")
        print(num * 10)
    }
    // 控制台输出:
    the index is 0
    20
    the index is 1
    30
    the index is 2
    40
    
  • Iterator 迭代器

    let numbers = [Int](2...4)
    var numIterator = numbers.makeIterator()
    while let num = numIterator.next() {
        print(num * 10)
    }
    // 控制台输出:20, 30, 40
    

索引

  • startIndex: 返回第一个元素的位置,对于数组来说永远为 0。

  • endIndex: 返回最后一个元素索引 +1 的位置,等同于数组的 count。

  • 如果数组为空,那么 startIndex 和 endIndex 相等。

  • indice 获取数组的索引区间

    let numbers = [Int](2...4)
    for i in numbers.indices {
        print(numbers[i] * 10)
    }
    // 控制台输出:20, 30, 40
    

查找操作

判断是否包含指定元素
  • contains(_:) 判断数组是否包含指定元素
  • contains(where:) 判断数组是否包含符合给定条件的元素
判断所有元素符合某个条件
  • allSatisfy(_:) 判断数组的没一个元素都符合给定的条件

    let array = [10, 20, 45, 30, 98, 101, 4]
    print(array.allSatisfy({ $0 > 10 }))
    print(array.allSatisfy({ $0 >= 4 }))
    // 控制台输出结果:
    false
    true
    
查找元素
  • first 返回数组第一个元素(optional),若数组为空,返回 nil。

  • last 返回数组最后一个元素(optional),若数组为空,返回 nil。

  • first(where:) 返回数组第一个符合给定条件的元素(optional)。

  • last(where:) 返回数组最后一个符合给定条件的元素(optional)。

    let array = [10, 20, 45, 30, 98, 101, 4] 
    print(array.first)
    print(array.last)
    print(array.first(where: { $0 > 25 }))
    print(array.last(where: { $0 > 25 }))
    // 控制台输出结果:
    Optional(10)
    Optional(4)
    Optional(45)
    Optional(101)
    
查找索引
  • firstIndex(of:) 返回给定的元素在数组中出现的第一个位置(optional)

  • lastIndex(of:) 返回给定的元素在数组中出现的最后一个位置(optional)

  • firstIndex(where:) 返回符合条件的第一个元素的位置(optional)

  • lastIndex(where:) 返回符合条件的最后一个元素的位置(optional)

    let array = [10, 20, 45, 30, 98, 101, 4, 20] 
    print(array.firstIndex(of: 30))
    print(array.lastIndex(of: 20)) 
    // 控制台输出结果:
    Optional(3)
    Optional(7)
    Optional(2)
    Optional(5)
    
查找最大最小元素
  • min() 返回数组中最小的元素

  • max() 返回数组中最大的元素

    let array = [10, 20, 45, 30, 98, 101, 4, 20]
    print(array.min())
    print(array.max())
    // 控制台输出结果:
    Optional(4)
    Optional(101)
    
  • min(by:) 利用给定的方式比较元素并返回数组中的最小元素

  • max(by:) 利用给定的方式比较元素并返回数组中的最大元素

    let array = [(45, "error1"), (20, "error2"), (30, "error3")]
    print(array.min(by: { a, b -> Bool in
        a.0 < b.0
    }))
    print(array.max(by: { a, b -> Bool in
        a.0 < b.0
    }))
    // 控制台输出结果:
    Optional((20, "error2"))
    Optional((45, "error1"))
    

添加 & 删除

末尾插入
  • append(_:) 在末尾追加一个元素

  • append(contentsOf:) 在末尾追加多个元素

    var array = [Int](1...3)
    array.append(10)
    print(array)
    array.append(contentsOf: 100..<105)
    print(array)
    // 控制台输出结果:
    [1, 2, 3, 10]
    [1, 2, 3, 10, 100, 101, 102, 103, 104]
    
任意位置插入
  • insert(_:at:) 在指定位置插入一个元素

  • insert(contentsOf:at:) 在指定位置插入多个元素

    var array = [Int](1...3)
    array.insert(-1, at: 0)
    print(array)
    // 控制台输出结果:[-1, 1, 2, 3]
    array.insert(contentsOf: 5..<7, at: 2)
    print(array)
    // 控制台输出结果:[-1, 1, 5, 6, 2, 3]
    
  • 字符串也是 Collection, Element 是 Character 类型。

    var chars : [Character] = ["a", "b", "c"]
    chars.insert(contentsOf: "hello", at: 0)
    print(chars)
    // ["h", "e", "l", "l", "o", "a", "b", "c"]
    
移除单个元素
  • remove(at:) 移除并返回指定位置的一个元素

    var chars : [Character] = ["a", "b", "c", "d"]
    let removedChar = chars.remove(at: 1)
    print(removedChar)
    print(chars)
    // b
    // ["a", "c", "d"]
    
  • removeFirst() 移除并返回数组的第一个元素

    var chars : [Character] = ["a", "b", "c", "d"]
    let removedChar = chars.removeFirst()
    print(removedChar)
    print(chars)
    // a
    //["b", "c", "d"]
    
  • removeLast() 移除并返回数组的最后一个元素

    var chars : [Character] = ["a", "b", "c", "d"]
    let removedChar = chars.removeLast()
    print(removedChar)
    print(chars)
    // d
    // ["a", "b", "c"]
    
  • popLast() 移除并返回数组的最后一个元素(optional),空数组返回 nil。

    var chars : [Character] = ["a", "b", "c", "d"]
    let popedChar = chars.popLast()
    print(popedChar)
    print(chars)
    // Optional("d")
    // ["a", "b", "c"]
    
移除多个元素
  • removeFirst(:) 移除数组前面多个元素

  • removeLast(:) 移除数组后面多个元素

    var chars : [Character] = ["a", "b", "c", "d", "e"]
    chars.removeLast(2)
    print(chars)
    // ["a", "b", "c"]
    chars.removeFirst(2)
    print(chars)
    // ["c"]
    
  • removeSubrange(_:) 移除数组中给定范围的元素

    var chars : [Character] = ["a", "b", "c", "d", "e"]
    chars.removeSubrange(1...2)
    print(chars)
    // ["a", "d", "e"]
    
  • removeAll() 移除数组所有的元素

    var chars : [Character] = ["a", "b", "c", "d", "e"]
    chars.removeAll()
    print(chars)
    // []
    print(chars.capacity)
    // 0
    
  • removeAll(keepingCapacity:) 移除数组所有的元素,保留数组的容量。

    var chars : [Character] = ["a", "b", "c", "d", "e"]
    chars.removeAll(keepingCapacity: true)
    print(chars)
    // []
    print(chars.capacity)
    // 5
    

数组切片(ArraySlice)

ArraySlice 是数组或者其他 ArraySlice 的一段连续切片,和原数组共享内存。党要改变 ArraySlice 的时候,ArraySlice 会 copy 出来,形成单独内存。ArraySlice 拥有和 Array 基本完全类似的方法。

arraySlice

通过 Drop 得到 ArraySlice
  • dropFirst(:) “移除”原数组前面指定个数的元素得到一个 ArraySlice

  • dropLast(:) “移除”原数组后面指定个数的元素得到一个 ArraySlice

  • drop(:) “移除”原数组符合指定条件的元素得到一个 ArraySlice

    let numbers = [5, 2, 10, 1, 0, 100, 46, 99]
    print(numbers.dropFirst())
    // [2, 10, 1, 0, 100, 46, 99]
    print(numbers.dropFirst(3))
    // [1, 0, 100, 46, 99]
    print(numbers.dropLast())
    // [5, 2, 10, 1, 0, 100, 46]
    print(numbers.dropLast(2))
    // [5, 2, 10, 1, 0, 100]
    print(numbers.drop(while: { $0 < 15 }))
    // [100, 46, 99]
    
通过 Prefix 得到 ArraySlice
  • prefix() 获取数组前面指定个数的元素组成的 ArraySlice

  • prefix(upTo:) 获取数组到指定索引位置(不包含指定位置)前面的元素组成的 ArraySlice

  • prefix(through:) 获取数组到指定索引位置(包含指定位置)前面的元素组成的 ArraySlice

  • prefix(while:) 获取数组前面符合条件的元素(到第一个不符合条件元素截止)组成的 ArraySlice

    let numbers = [5, 2, 10, 1, 0, 100, 46, 99]
    print(numbers.prefix(3))
    // [5, 2, 10]
    print(numbers.prefix(upTo: 4))
    // [5, 2, 10, 1]
    print(numbers.prefix(through: 4))
    // [5, 2, 10, 1, 0]
    print(numbers.prefix(while: { $0 < 10 }))
    // [5, 2]
    
通过 Suffix 得到 ArraySlice
  • suffix() 获取数组后面指定个数的元素组成的 ArraySlice

  • suffix(from:) 获取数组从指定索引位置到结尾(包含指定位置)的元素组成的 ArraySlice

    let numbers = [5, 2, 10, 1, 0, 100, 46, 99]
    print(numbers.suffix(3))
    // [100, 46, 99]
    print(numbers.suffix(from: 3))
    // [1, 0, 100, 46, 99]
    
通过 Range 得到 ArraySlice

可以通过对数组下标指定 Range 获取 ArraySlice,可以使用闭区间、半开半闭区间、单侧区间、甚至...来获取整个数组组成的 ArraySlice。

let numbers = [5, 2, 10, 1, 0, 100, 46, 99]
print(numbers[3...5])
// [1, 0, 100]
print(numbers[3..<5])
// [1, 0]
print(numbers[...2])
// [5, 2, 10]
print(numbers[..<2])
// [5, 2]
print(numbers[6...])
// [46, 99]
print(numbers[...])
// [5, 2, 10, 1, 0, 100, 46, 99]

ArraySlice 无法直接赋值给一个 Array 的常量或者变量,需要使用 Array(slice)

let numbers = [5, 2, 10, 1, 0, 100, 46, 99]
let slice = numbers.prefix(3) 
let array = Array(slice)
print(array)
// [5, 2, 10]

ArraySlice 和原 Array 相互独立,它们添加删除元素不会影响对方。

var array = [10, 46, 99]
var slice = array.dropLast()
array.append(333)
print(slice)
// [10, 46]
slice.append(555)
print(array)
// [10, 46, 99, 333]

重排操作

随机化
  • shuffle() 在原数组上将数组元素打乱,原数组发生改变。

    var array = [Int](1...8)
    array.shuffle()
    print(array)
    // [4, 5, 1, 8, 6, 2, 3, 7]
    
  • shuffled() 返回一个原数组的随机化数组,原数组不变,生成新的数组。

    var array = [Int](1...8) 
    let numbers = array.shuffled()
    print(numbers)
    print(array)
    // [6, 4, 3, 7, 2, 8, 5, 1]
    // [1, 2, 3, 4, 5, 6, 7, 8]
    
逆序
  • reverse() 在原数组上将数组逆序,原数组发生改变。

    var array = [Int](1...8)
    array.reverse()
    print(array)
    // [8, 7, 6, 5, 4, 3, 2, 1]
    
  • reversed() 返回原数组的逆序“集合表示”,该方法不会分配内存空间。

    var array = [Int](1...8)
    let numbers = array.reversed()
    print(numbers)
    // ReversedCollection<Array<Int>>(_base: [1, 2, 3, 4, 5, 6, 7, 8])
    print(array)
    // [1, 2, 3, 4, 5, 6, 7, 8]
    for i in numbers {
        print(i)
    }
    // 控制台输出:8,7,6,5,4,3,2,1
    
分组

partition(by belongsInSecondPartition: (Element) throws -> Bool) 将数组以某个条件分组,数组的前半部分是不符合条件的元素,后半部分都是符合条件的元素

var array = [10, 20, 45, 30, 98, 101, 30, 4]
let index = array.partition { (element) -> Bool in
    element > 30
}
let partition1 = array[..<index]
let partition2 = array[index...]
print(array)      // [10, 20, 4, 30, 30, 101, 98, 45]
print(partition1) // [10, 20, 4, 30, 30]
print(partition2) // [101, 98, 45] 
排序
  • sort() 在原数组上将元素排序,改变原数组

    var array = [10, 20, 45, 30, 98, 101, 30, 4]
    array.sort()
    print(array) // [4, 10, 20, 30, 30, 45, 98, 101]
    
  • sorted() 返回排序后的结果数组,原数组不变

    let array = [10, 20, 45, 30, 98, 101, 30, 4]
    let numbers = array.sorted()
    print(array)   // [10, 20, 45, 30, 98, 101, 30, 4]
    print(numbers) // [4, 10, 20, 30, 30, 45, 98, 101]
    
交换元素

swapAt(_:_:) 交换指定位置的两个元素, 会修改原数组。

var array = [10, 20, 45, 30, 98, 101, 30, 4]
array.swapAt(array.startIndex, array.endIndex-1)
print(array) // [4, 20, 45, 30, 98, 101, 30, 10]

拼接操作

字符串数组拼接
  • joined() 拼接字符串数组里的所有元素为一个字符串。

  • joined(separator:) 以给定的分隔符拼接字符串数组里的所有元素为一个字符串。

    let array = ["hello", "world"]
    print(array.joined())                // helloworld
    print(array.joined(separator: ","))  // hello,world
    
Sequence 数组拼接
  • joined() 拼接数组里的所有元素为一个更大的 Sequence。

    let ranges = [0..<3, 8..<10, 15..<17]
    for range in ranges {
        print(range)
    }
    // 0..<3
    // 8..<10
    // 15..<17
    for index in ranges.joined() {
        print(index, terminator: " ")
    }
    // 0 1 2 8 9 15 16
    
  • joined(separator:) 以给定的分隔符拼接数组里的所有元素为一个更大的 Sequence。

    let nestedNumbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    let joinedNumbers = nestedNumbers.joined(separator: [-1, -2])
    print(Array(joinedNumbers))
    // [1, 2, 3, -1, -2, 4, 5, 6, -1, -2, 7, 8, 9]
    

数组应用

用数组实现栈

栈(Stack)是一种先入后出(last in first out)的数据结构,仅限定在栈顶进行插入或者删除操作。栈结构的实际应用主要有数制转换、括号匹配、表达式求值等。

栈的结构

栈的代码实现

var stack = Stack<Int>()
stack.push(1)
stack.push(2)
stack.push(3)
print(stack.pop() ?? 0) // 3
print(stack.count)      // 2

用数组实现队列

队列(Queue):先进先出(first in first out)

队列结构

队列代码实现

var queue = YYQueue<Int>()
queue.enqueue(1)
queue.enqueue(2)
queue.enqueue(3)
print(queue.dequeue() ?? 0)  // 1
print(queue)    // YYQueue<Int>(elements: [2, 3])