swift中的map, filter, reduce
2019-12-23
Premature optimisation is the root of all evil.
- map
map 理解为对数组中每个元素进行一个相同的操作, 然后返回到原来的位置(元素之间不互相影响)
map 的标准格式:
var arr: [Int] = [1,2,3,4,5,6,7]
arr.map { (<#Int#>) -> T in
<#code#>
}
如
arr.map { (aValue: Int) -> Int in
aValue + 1
} //返回一个[Int], 元素分别是原[Int]的每一个元素加一
//>>>[2, 3, 4, 5, 6, 7, 8]
//优秀写法
arr.map {aValue in aValue + 1}
//更优秀写法
arr.map {$0 + 1}
//$0 代表map的第0个参数
- filter
filter 理解为对数组中每个元素进行一个相同的判断, 判断为真则返回当前元素
==(filter的返回值必须为Bool)==
filter 的标准格式:
var arr: [Int] = [1,2,3,4,5,6,7]
arr.filter({ (<#Int#>) -> Bool in
<#code#>
})
如
arr.filter({ (aValue: Int) -> Bool in
aValue > 4
}) //返回一个[Int], 元素分别是判断"大于4"为真的元素
//>>>[5, 6, 7]
//优秀写法
arr.filter({aValue in aValue > 4})
//更优秀写法
arr.filter({$0 > 4})
//$0 是filter第0个参数
//尾随闭包写法
arr.filter(){$0 > 4}
//or
arr.filter {$0 > 4}
- reduce
理解为把每一个元素 经过某个规则 合并成一个东西
reduce 有两种实现
reduce(initialResult: , nextPartialResult: )
的标准格式:
var arr: [Int] = [1,2,3,4,5,6,7]
arr.reduce(Result, { (<#Result#>, <#Int#>) -> Result in
<#code#>
})
如
arr.reduce(0, { (resu, aValue) -> Int in
resu + aValue
}) //参数resu是reduce的第一个参数0, 参数aValue是arr中的每一个元素, 每一次调用闭包, 返回值都会被保存到resu里, 作为下一次调用闭包的参数. 最后返回resu.
//>>>28
//优秀写法
arr.reduce(0){ resu, aValue in resu + aValue }
//更优秀写法
arr.reduce(0){ $0 + $1 }
//对于个别运算
arr.reduce(0, +) //在这里, 左参数为上面的resu, 右参数为上面的aValue
reduce(into: , updateAccumulatingResult: )
的标准格式:
var arr: [Int] = [1,2,3,4,5,6,7]
arr.reduce(into: Result, { (<#inout Result#>, <#Int#>) in
<#code#>
})
如
arr.reduce(into: [], { (resu, aValue) in
resu.append(aValue)
})
//优秀写法
arr.reduce(into: []) { (resu, aValue) in resu.append(aValue) }
//更优秀写法
arr.reduce(into: []) { $0.append($1) }
这个方法适用于有 copy-on-write
特性的类型(如 字典, 数组, 集合等)
This method is preferred over
reduce(_:_:)
for efficiency when the result is a copy-on-write type, for example an Array or a Dictionary. ——Apple文档
(如Int等类型会直接复制)
计算字符串中各个字符个数
let s = "Hello world!"
s.reduce(into: [:]){ $0[$1, default: 0] += 1}
//>>>["w": 1, "H": 1, "l": 3, " ": 1, "e": 1, "d": 1, "o": 2, "!": 1, "r": 1]
- 链式语法
如
//求arr数组中每个元素乘3后的偶数数组, 并将得到的数组每个元素相加减100
var arr: [Int] = [1,2,3,4,5,6,7]
arr.map{$0 * 3}.filter{$0 % 2 == 0}.reduce(-100){$0 + $1}
//-64
补充:
- flatMap
将数组降低一个纬度
var a = [[5, 2, 7], [4, 8], [9, 1, 3], [1,[2,3],4] ]
a.flatMap{$0}
//>>>[5, 2, 7, 4, 8, 9, 1, 3, 1, [2, 3], 4]
flatMap还有一个重载可以将Optional类型解包, 但是会有警告:
‘flatMap’ is deprecated: Please use compactMap(_:) for the case where closure returns an optional value Use ‘compactMap(_:)’ instead
- compactMap
可以把一个集合中的空值去除,并且返回一个去除nil值得数组
其实就是对flatMap第二个重载的重命名
//听说命名是参考了Ruby的Array::compact方法
let numbers = ["1", "2", "three", "5 - 1", "5"]
let mapResult = numbers.map { (number) -> Int? in
return Int(number)
}
//>>>[Optional(1), Optional(2), nil, nil, Optional(5)]
let compactMapResult = numbers.compactMap { (number) -> Int? in
return Int(number)
}
//>>>[1, 2, 5]