试着去使用 map 和 reduce,但这不是强制的。当合适的时候,使用 for 循环也无可厚非。高阶函数的意义是让代码可读性更高。但是如果使用 reduce 的场景难以
理解的话,强行使用往往事与愿违,这种时候简单的 for 循环可能会更清晰。
1.1.1、map
普通for
循环
let numGroup: [Int] = [1,2,3,4,5]
var numGroupNew: [Int] = []
for num in numGroup {
numGroupNew.append(num * num)
}
print(numGroupNew) // [1, 4, 9, 16, 25]
尝试map
函数
先看效果
let numGroupMap0: [Int] = numGroup.map { (num) -> Int in
return num * num
}
print(numGroupMap0) // [1, 4, 9, 16, 25]
// 简化
let numGroupMap1: [Int] = numGroup.map { num in return num * num }
print(numGroupMap1) // [1, 4, 9, 16, 25]
//再简化
let numGroupMap2 = numGroup.map { $0 * $0 }
print(numGroupMap2) // [1, 4, 9, 16, 25]
好吧....最后就用了一行代码就完成了。
它很短而且比原来更清晰。所有无关的内容都被移除了。
map
:可以对数组中的每一个元素做一次处理
1.1.2、flatMap
let numGroupFlatMap = numGroup.flatMap { $0 * $0 }
print(numGroupFlatMap)
等等...这好像和map一样嘛,也是对数组中的每一个元素做一次处理。
那他们两者有何区别呢,我们再试一下
let arrxx = array.map { $0.count} //[5, 6, 6, 0]
let arryy = array.flatMap { $0.count} //[5, 6, 6, 0]
这还是一样啊.... 再等等,一定是我的打开方式不对。我们展开再捋一下~
let array = ["apple", "orange", "banana", ""]
let arr1 = array.map { a -> Int? in
let length = a.count
guard length > 0 else { return nil }
return length
}
print(arr1) //[Optional(5), Optional(6), Optional(6), nil]
let arr2 = array.flatMap { a-> Int? in
let length = a.count
guard length > 0 else { return nil}
return length
}
print(arr2) //[5, 6, 6]
发现了,不对,怎么map
返回的数组都带Optional
,最后空字符串也变成了nil
flatMap返回后的数组中不存在nil,同时它会把Optional解包
还有一个🌰
let group = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let groupA = array.map{ $0 }
print(groupA) // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let groupB = array.flatMap{ $0 }
print(groupB) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
原来flatMap还能把数组中存有数组的数组(二维数组、N维数组)一同打开变成一个新的数组
map
和 filter
随便举一个🌰
let fruits = ["Apple", "Orange", "Banana"]
let counts = [2, 3, 5]
let array = counts.flatMap { count in
fruits.map ({ fruit in
return fruit + " \(count)"
})
}
2、Filter
filer
:过滤,可以对数组中的元素按照某种规则进行一次过滤
let nums = [1,2,3,4,5,6,7,8,9,10]
nums.filter { $0 % 2 == 0 } // [2, 4, 6, 8, 10]
连和之前的 map
我们还能来个组合击
(1..<10).map { $0 * $0 }.filter { $0 % 2 == 0 } // [4, 16, 36, 64]
在喵神的 Swift 进阶书中提到
一个关于性能的小提示:如果你正在写下面这样的代码,请不要这么做!
bigArray.filter { someCondition }.count > 0
filter 会创建一个全新的数组,并且会对数组中的每个元素都进行操作。然而在上面这段代码中,这显然是不必要的。在这个情景下,使用 contains(where:) 更为合适:
bigArray.contains { someCondition }
3、reduce
reduce
方法把数组元素组合计算为一个值。
传统实现:
var sum = 0
for money in moneyArray {
sum = sum + money
}
再看看数字相乘
var product = 1
for money in moneyArray {
product = product * money
}
那再看一下reduce如何实现
var sumReduce0 = moneyArray.reduce(0,{$0 + $1})
//简化 ~
var sumReduce1 = moneyArray.reduce(0,+)
他的方法为:
public func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
他的的API文档
/// Returns the result of combining the elements of the sequence using the
/// given closure.
///
/// Use the `reduce(_:_:)` method to produce a single value from the elements
/// of an entire sequence. For example, you can use this method on an array
/// of numbers to find their sum or product.
///
/// The `nextPartialResult` closure is called sequentially with an
/// accumulating value initialized to `initialResult` and each element of
/// the sequence. This example shows how to find the sum of an array of
/// numbers.
///
/// let numbers = [1, 2, 3, 4]
/// let numberSum = numbers.reduce(0, { x, y in
/// x + y
/// })
/// // numberSum == 10
///
/// When `numbers.reduce(_:_:)` is called, the following steps occur:
///
/// 1. The `nextPartialResult` closure is called with `initialResult`---`0`
/// in this case---and the first element of `numbers`, returning the sum:
/// `1`.
/// 2. The closure is called again repeatedly with the previous call's return
/// value and each element of the sequence.
/// 3. When the sequence is exhausted, the last value returned from the
/// closure is returned to the caller.
///
/// If the sequence has no elements, `nextPartialResult` is never executed
/// and `initialResult` is the result of the call to `reduce(_:_:)`.
///
/// - Parameters:
/// - 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.
/// - Returns: The final accumulated value. If the sequence has no elements,
/// the result is `initialResult`.
真的..辣么长,简直比农药里杨玉环的技能解释还长n倍。
大致总结一下就是
返回一个Result
类型,以及接收两个参数,一个为类型Result
的初始值,另一个为把类型为Result
的元素和类型为Element
的元素组合成一个返回Result
的值的函数。
我们再看看API中的🌰
let numbers = [1, 2, 3, 4]
let numberSum = numbers.reduce(0, { x, y in
x + y
})
x为计算结果,y为数组元素,他们的类型可以不一样,x代表的是计算后返回得来的类型,y是数组元素的类型。
那这例子我们稍微调整一下
let numberStr = numbers.reduce("", { x, y in
x + "\(y)"
})
// numberStr == 1234
当然reduce
还有很多骚操作。这篇只是个抛砖引玉~ 希望能给自己给大家一点点的收获。
相关推荐~
https://www.jianshu.com/p/6f45a6f99411
https://blog.csdn.net/youshaoduo/article/details/65629909