swift数组简介2

99 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第12天,点击查看活动详情

将函数行为参数化

  • map 和 CompactMap - 对元素进行变换
  • filter - 筛选
  • reduce - 将元素合并到一个总和的值
  • squence - 下一个元素
  • forEach - 对于一个元素执行怎样的操作
  • sort,lexicographicCompare 和 partition - 两个元素应该以怎样的顺序进行排列
  • first, firstIndex, contains - 元素是否符合某一个条件
  • elementsEqual和starts - 俩个元素是否相等
  • split - 这个元素是否是封割符
  • prefix - 判断为真,将元素过滤出来,一旦不为真,就将剩余结果抛弃,和filter类似,但是会提前退出。这个函数在处理无限序列或者延迟家孙(lazily-computed)的时候非常有用
  • drop - 判断为真,丢弃元素,一旦不为真,将剩余结果返回。和prefix(while:)相似,不过返回相反的集合

Filter

(1..<10).map { $0 * $0 }.filter { $0 % 2 == 0 } // [4, 16, 36, 64]

实现源码

extension Array {
  func filter(_ isIncluded: (Element) -> Bool) -> [Element] {
      var result: [Element] = []
      for x in self where isIncluded(x) {
      result.append(x)
      }
  return result
  }
}

对于判断条件filter的性能比contains低,因为contains不会因为计数而去全新创建一个数组,并且一旦找到第一个元素就会退出

Reduce

所有值合并为新值

let sum = fibs.reduce(0) { total, num in total + num } // 12
fibs.reduce(0, +) // 12

输入的值和输出的值可以不同

print(array.reduce("") { str, num in str + "(num)," })
// 0,1,1,2,3,5

实现源码

extension Array {
  func reduce<Result>(_ initialResult: Result,
                      _ nextPartialResult: (Result, Element) -> Result) -> Result
  {
      var result = initialResult
      for x in self {
          result = nextPartialResult(result, x)
      }
      return result
  }
}

Reduce实现map和filter

extension Array {
  func map2<T>(_ transform: (Element) -> T) -> [T] {
      return reduce([]) {
          $0 + [transform($1)]
      }
  }
  func filter2(_ isIncluded: (Element) -> Bool) -> [Element] {
      return reduce([]) {
          isIncluded($1) ? $0 + [$1] : $0
      }
  }
}

For Each

对集合中每个元素调用一个函数,return不能返回到函数的作用域之外,他做的仅仅是从闭包中返回

array.forEach{
  print($0)
  if $0 > 2 {
      return
  }
  print($0)
}
0
0
1
1
1
1
2
2
3
5

切片

通过下标获取元素

let slice = array[1...]
print(slice)
print(type(of: slice))

[1, 1, 2, 3, 5]
ArraySlice<Int>

切片类型ArraySlice只是一种表示方式,它的背后仍然是原来的数组。因为数组的元素不会被复制,所以创建一个切片的代价是很小的。

[图片上传失败...(image-8e753c-1635170375028)]

ArraySlice和Array都满足了相同的协议(当中最重要的是Collection协议),所以可以把切片当数组处理

let newArray = Array(slice)
type(of: newArray) // Array<Int>

如果是切片用startIndex 和 endIndex 属性做索引计算。