《Advanced Swift》笔记2:数组变形(二)—— filter 和 reduce | LiJun's Blog
本文将介绍filter和reduce两个高阶函数的使用和内部实现。
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])`. 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 } } |