即为先导值澳门永利备用网址,去掉无关的修饰词

Reduce

声明

func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result

Returns the result of combining the elements of the sequence using the
given closure.
动用给定的block来整合集合中的成分,并且重临组合后的结果

参数

initialResult
The value to use as the initial accumulating value. initialResult is
passed to nextPartialResult the first time the closure is executed.
初始值

nextPartialResult
A closure that combines an accumulating value and an element of the
sequence into a new accumulating value, to be used in the next call of
the nextPartialResult closure or returned to the caller.
包含五个参数的block,block的首先个参数为事先的乘除结果,若是是第三回统计,则暗许为initialResult。第四个参数为汇聚中的下3个要素。重回值为遍历完全数集合后的构成结果。block中可以定义七个参数的组成规则。

例如

let da = [1, 2, 3, 4, 5]
let sum = da.reduce(0) { (result: Int, ele: Int) -> Int in
    return result + ele
}
// sum = 15

对数组da中的成分求和,第三个参数0为初步值,当数组第几回进行result + ele //ele = data[0]时,此时的result即为发轫值。
可简写为

let da = [1, 2, 3, 4, 5]
let sum = da.reduce(0) {
    return $0 + $1
}
// sum = 15

或者

let da = [1, 2, 3, 4, 5]
let sum = da.reduce(0, +)
// sum = 15

注:斯维夫特中操作符为函数,函数允许拔取和block具有同样参数的函数作为参数代替block

上述代码的效应也等于

let da = [1, 2, 3, 4, 5]
var sum = 0
for i in 0..<da.count {
    sum += da[i]
}
// sum = 15

前言:swift是一门很优雅,很简短,成效很强劲的言语,同时也是一门很复杂的语言。进门相比较简单,看完苹果官方的文档就足以主导入门,进阶很难,很多比较好用的特征要求深刻研究。

Map & FlatMap

1.高阶函数

Wikipedia中定义,高级函数足足满意下边3个标准:

  • 收到2个要么七个函数作为传播参数
  • 把函数作为再次回到结果

举个例证:

func higherOrderFunction(str: String, argument: ((String) -> String)) -> String {
    return argument(str)
}
let result = higherOrderFunction(str: "hello world!", argument: {$0})   
//hello world!
//接收一个传入值和返回值都为字符串的函数为参数,返回一个字符串位结果

Map

Returns an array containing the results of mapping the given closure
over the sequence’s elements.
动用给定的block将数组映射为一个新的数组。新的数组元素为block中安装的投射规则规定。

参数:

transform
A mapping closure. transform accepts an element of this sequence as
its parameter and returns a transformed value of the same or of a
different type
三个block,参数为数组中的三个成分,block重临贰个使用映射规则转换之后的要素。
例如

let cast = ["Vivien", "Marlon", "Kim", "Karl"]
let lowercaseNames = cast.map { $0.lowercased() }
// 'lowercaseNames' == ["vivien", "marlon", "kim", "karl"]
let letterCounts = cast.map { $0.count }
// 'letterCounts' == [6, 6, 3, 4]

2.主旨接纳

  • ** Map**

map接收3个闭包作为参数,然后遍历整个数组,执行闭包里面的操作,可以视作对数组里存有的因素做了3个炫耀,再次回到来的是一个数组。

举个例子:

let numbers = [1, 2, 3, 4, 5, 6, 7, 8]
let result = numbers.map{$0+2}  //[3, 4, 5, 6, 7, 8, 9, 10]

先来看一下map的定义:

func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]

去掉毫不相关的修饰词:

func map<T>(_ transform: (Element) -> T) -> [T]

能够看出来map接收了三个闭包transform为参数,闭包参数是Element代表数组里的多个因素,重回值是二个范型,和传播参数类型非亲非故,并且闭包的重返值和map函数的重返值是千篇一律类型,都以范型T,相当于说map能够回来和数组成分不相同等类型的值
举个例证:

let numbers = [1, 2, 3, 4, 5, 6, 7, 8]
let result = numbers.map{"No.\($0)"}  //["No.1", "No.2", "No.3", "No.4", "No.5", "No.6", "No.7", "No.8"]

再进一步,我们去看一下map的源码完毕

  @_inlineable
  public func map<T>(
    _ transform: (Iterator.Element) throws -> T
  ) rethrows -> [T] {
    // TODO: swift-3-indexing-model - review the following
    let count: Int = numericCast(self.count)
    if count == 0 {
      return []
    }

    var result = ContiguousArray<T>()
    result.reserveCapacity(count)

    var i = self.startIndex

    for _ in 0..<count {
      result.append(try transform(self[i]))
      formIndex(after: &i)
    }

    _expectEnd(of: self, is: i)
    return Array(result)
  }

最重点的代码

var result = ContiguousArray<T>()
for _ in 0..<count {
  result.append(try transform(self[i]))
  formIndex(after: &i)
}

新兴成一个数组,数组里面填充闭包操作后的重返值,最后回来该数组。所以,map高阶函数适合部分急需对全体数组成分做一些很是操作的要求。

  • flatMap

flatMap函数和map函数达成的作用几乎,差距在于,flatMap有七个重载,多个威迫解包去掉数组中nil成分,七个将二维数组降为一个人数组。

(1). 遍历数组:

let numbers = [1, 2, 3, 4, 5, 6, 7, 8]
let result = numbers.flatMap{$0}  //[1, 2, 3, 4, 5, 6, 7, 8]

(2).数组降维

let numbers = [[1, 2, 3, 4], [5, 6, 7, 8]] 
let result = numbers.flatMap{$0}  //[1, 2, 3, 4, 5, 6, 7, 8]
let result2 = numbers.map{$0}  //[[1, 2, 3, 4], [5, 6, 7, 8]]

(3).去掉数组中nil

let numbers = [1, 2, 3, 4, nil]    //[Optional(1), Optional(2), Optional(3), Optional(4), nil]
let result = numbers.flatMap{$0}  //[1, 2, 3, 4]去掉nil,解包输出
let result = numbers.map{$0}  //[Optional(1), Optional(2), Optional(3), Optional(4), nil]

注意:

//非二维数组,数组不能和非数组合并
let numbers = [1, 2, 3, 4, [5, 6]] as [Any]   //[1, 2, 3, 4, [5, 6]]
let result = numbers.flatMap{$0}  //[1, 2, 3, 4, [5, 6]]
let result2 = numbers.map{$0}  //[1, 2, 3, 4, [5, 6]]

//数组中的数组包含nil值,因为并不是数组和数组的操作,元素不会合并成一个数组,所以,数组中的数组不会被遍历,原样输出
let numbers = [1, 2, 3, 4, [5, 6, nil]] as [Any]   //[1, 2, 3, 4, [Optional(5), Optional(6), nil]]
let result = numbers.flatMap{$0}  //[1, 2, 3, 4, [Optional(5), Optional(6), nil]]

//因为数组元素其中一个为nil,去掉nil,解包输出
let numbers = [[1, 2, 3, 4], [5, 6], nil]  //[Optional([1, 2, 3, 4]), Optional([5, 6]), nil]
let result = numbers.flatMap{$0}  //[[1, 2, 3, 4], [5, 6]]

//数组包含两个数组和一个nil,去掉nil,解除最外层包输出
let numbers = [[1, 2, 3, 4], [5, 6, nil], nil]   //[Optional([Optional(1), Optional(2), Optional(3), Optional(4)]), Optional([Optional(5), Optional(6), nil]), nil]
let result = numbers.flatMap{$0}  //[[Optional(1), Optional(2), Optional(3), Optional(4)], [Optional(5), Optional(6), nil]]

//数组和数组合并
let numbers = [[1, 2], [3, 4, nil]]   //[[Optional(1), Optional(2)], [Optional(3), Optional(4), nil]]
let result = numbers.flatMap{$0}  //[Optional(1), Optional(2), Optional(3), Optional(4), nil]

由地点的例证,引出三个难题:
1.怎么去掉nil
2.怎么野蛮解包
3.怎么样将二维数组降维

先看一下flatMap的定义:

func flatMap<SegmentOfResult : Sequence>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Iterator.Element]
func flatMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]

去掉不相干的修饰词:

func flatMap<SegmentOfResult : Sequence>(_ transform: (Element) -> SegmentOfResult) -> [SegmentOfResult.Iterator.Element]
func flatMap<ElementOfResult>(_ transform: (Element) -> ElementOfResult?) -> [ElementOfResult]

第四个重载接收的闭包重回值是可选类型(Optional),推断去掉数组中的nil和解包操作都在这一个重载;第一个重载接收闭包再次来到的是Sequence类型,可以把它作为是数组,那么二维数组降维应该调的是首先个重载,具体是或不是不错的,继续深刻看flatMap的源码完成

flatMap第一个重载

  @_inlineable
  public func flatMap<SegmentOfResult : Sequence>(
    _ transform: (${GElement}) throws -> SegmentOfResult
  ) rethrows -> [SegmentOfResult.${GElement}] {
    var result: [SegmentOfResult.${GElement}] = []
    for element in self {
      result.append(contentsOf: try transform(element))
    }
    return result
  }

flatMap接收的闭包重临值是Sequence,可以当做数组。重点代码:

result.append(contentsOf: try transform(element))

本条函数有啥样效益呢?那几个函数的意义就是把element数组里面的因素逐个取出来,然后添加到result数组的背后,那就是flatMap能够将二维数组降维成一维数组的原因,函数描述:

Adds the elements of a sequence to the end of the array.

举个例证:

var nums1 = [1, 2, 3, 4]
let nums2 = [5, 6, 7, 8, 9]
nums1.append(contentsOf: nums2)  //[1, 2, 3, 4, 5, 6, 7 ,8, 9]

flatMap第2个重载

  @_inlineable
  public func flatMap<ElementOfResult>(
    _ transform: (${GElement}) throws -> ElementOfResult?
  ) rethrows -> [ElementOfResult] {
    var result: [ElementOfResult] = []
    for element in self {
      if let newElement = try transform(element) {
        result.append(newElement)
      }
    }
    return result
  }

flatMap接收的闭包再次回到值是可选类型(Optional),看一下相当首要代码:

for element in self {
  if let newElement = try transform(element) {
    result.append(newElement)
  }
}

element就是数组里的每三个因素,”let newElement =
transform(element)”,关键的一段代码,let常量无法为nil,所以,当transform(element)=nil,就被过滤掉了,并且newElement不是可选类型,所以,那里会解包赋值。

  • reduce

Returns the result of combining the elements of the sequence using the
given closure.

简单来说点来说就是一路处理数组的各种成分,举个例证求和:

let numbers =  [1, 2, 3, 4, 5]
let sum = numbers.reduce(0, {$0+$1})  //15
//0是输入的初始值,$0,$1分别是闭包的第一个参数和第二个参数

不自然必要和,比如生成字符串:

let numbers =  [1, 2, 3, 4, 5]
let sum = numbers.reduce("", {"\($0)\($1)"})  //"12345"

废话不多说,直接上源码

  @_inlineable
  public func reduce<Result>(
    _ initialResult: Result,
    _ nextPartialResult:
      (_ partialResult: Result, ${GElement}) throws -> Result
  ) rethrows -> Result {
    var accumulator = initialResult
    for element in self {
      accumulator = try nextPartialResult(accumulator, element)
    }
    return accumulator
  }

新兴成多少个变量accumulator,每一回执行完闭包都把值赋给accumulator。闭包传进去的参数为上两遍的值和近来数组元素,所以,大家可以将一切数组的值累加起来。

  • filter

Returns an array containing, in order, the elements of the sequence
that satisfy the given predicate.

大概来说就是从3个数组筛选出符合条件的要素,以数组的格局再次来到。举个例子,筛选出<3的因素:

let numbers =  [1, 2, 3, 4, 5]
let sum = numbers.filter{$0<3} //[1, 2]

FlatMap

flatMap(_:)map(_:)无异于,也是足以将二个凑合通过某种映射规则映射为另3个会面,区其他地点是,flatMap(_:)会将映射之后的成分强解包(unwraped),假使蒙受nil,则将其过滤到,重回的新集合为过滤掉nil之后的成团;map(_:)回去的因素为Optional品种成分,借使集合中有nil,则赶回的汇集中也包·括nil,其余因素均为Optional类型。
例如:

let cast = [nil, "Marlon", "Kim", "Karl"]
let uppercaseNames = cast.map { $0?.uppercased() } //1
// 'uppercaseNames' = [nil, Optional("MARLON"), Optional("KIM"), Optional("KARL")]
let foo = cast.flatMap { $0?.uppercased() }//2
// 'foo' = ["MARLON", "KIM", "KARL"]

1、将数组cast辉映为1个新的数组,给定的照射规则是$0?.uppercased(),即将数组中的字符串全部转换来大写的方式,再次回到的新数组的要素为optional类型。
2、将数组cast炫耀为多个新的数组,给定的映射规则是$0?.uppercased(),即将数组中的字符串全体转换到大写的款式,并且将回到的数组成分解包,
如若成分为nil,则过滤掉。

3.总结

刚先导读书这个高阶函数,还挺难懂的,可是如果懂了,就像虎添翼,用起来拾分爽。

参考
斯威夫特 烧脑体操(三) –
高阶函数

谈谈 Swift 中的 map 和
flatMap

Higher Order Functions: Map, Filter, Reduce and
more

Filter

Returns an array containing, in order, the elements of the sequence
that satisfy the given predicate.
重回3个数组,该数组按顺序包蕴满意给定谓词的队列元素。

参数

isIncluded
A closure that takes an element of the sequence as its argument and
returns a Boolean value indicating whether the element should be
included in the returned array.
一个block,将集结的要素作为参数,并回到1个Boolean,用来指示那个因素是或不是包括在回到的数组中,若是包蕴,则将其添插手数组。

例如

let cast = ["Vivien", "Marlon", "Kim", "Karl"]
let shortNames = cast.filter { $0.count < 5 }
print(shortNames)
// Prints "["Kim", "Karl"]"

上述代码的效用为:筛选闻明字的字数小于5的名字,{ $0.count < 5 }本条block为筛选的谓词,$0为block的参数,即shortNames的元素。