《Advanced Swift》笔记2:数组变形(二)—— filter 和 reduce

本文将介绍filterreduce两个高阶函数的使用和内部实现。

filter

filter方法可以过滤掉数组中不符合条件的元素,返回包含所有符合条件的元素的数组。比如现在需要选出一个数组中所有的偶数,传统的做法是这样的

1
2
3
4
5
6
7
8
let numbers = [1, 2, 3, 4, 5]
var evens = [Int]()
for num in numbers {
if num % 2 == 0 {
evens.append(num)
}
}
print(evens) // [2,4]

map方法一样,filter也是讲for循环中的代码块用闭包封装了,我们只需要在闭包中传入筛选条件即可:

1
2
3
let numbers = [1, 2, 3, 4, 5]
let evens = numbers.filter{$0 % 2 == 0}
print(evens) // [2,4]

使用filter方法的优点和map方法一样,代码简洁、语义清晰、更安全。

filter的内部实现和map差不多,就是在像新数组添加元素时增加了一个条件判断。可以这样实现它:

1
2
3
4
5
6
7
8
9
10

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

点击查看源码,然而我并没有完全看懂,囧。

reduce

1
2
3
4
5
6
7
8
9
extension SequenceType {
/// Returns the result of repeatedly calling `combine` with an
/// accumulated value initialized to `initial` and each element of
/// `self`, in turn, i.e. return
/// `combine(combine(...combine(combine(initial, self[0]),
/// self[1]),...self[count-2]), self[count-1])`.
@warn_unused_result
public func reduce<T>(initial: T, @noescape combine: (T, Self.Generator.Element) throws -> T) rethrows -> T
}

从文档来看,reduce方法就是传入一个初始值和合并函数,然后计算合并后的值并返回,相比之前的map,flatMap,filter都是返回一个新的数组不同,这里只是返回一个元素合并后的新元素。比如我们想要将数组的元素全部加起来,可以这样写:

1
2
3
4
5
6
7

let numbers = [1, 2, 3, 4, 5]
var result = 0
for num in numbers {
result = result + num
}
print(reduce) // 15

reduce,也只需要一句代码:

1
2
3
let numbers = [1, 2, 3, 4, 5]
let reduce = numbers.reduce(0, combine: +)
print(reduce) // 15

因为在Swift中,运算符也是函数,因此可以将运算符作为参数传入。
我们可以这样实现一个reduce函数:

1
2
3
4
5
6
7
8
9
extension Array {
func my_reduce<U>(initial: U, combine: (U, Element) -> U) -> U {
var result = initial
for x in self {
result = combine(result, x)
}
return result
}
}
坚持原创技术分享,您的支持将鼓励我继续创作!