函数式编程之 map

我们常常需要对一个数组中的每一个元素进行相应的转换,例如,下面这个函数将数组中的每个元素增加 1.

1
2
3
4
5
6
7
func incrementArray(xs: [Int]) -> [Int] {
var result: [Int] = []
for x in xs {
result.append(x + 1)
}
return result
}

然而仔细考虑之后我们会发现,如果有其他的转化操作,就需要再重新写一个函数,而其他的代码逻辑都是相同的,所以,这里我们可以将转化部分的逻辑抽取成一个闭包,如下:

1
2
3
4
5
6
7
func doSomeThingOnArray(xs: [Int], transform: Int -> Int) -> [Int] {
var result: [Int] = []
for x in xs {
result.append(transform(x))
}
return result
}

这样,我们就将会变化的代码抽取出来了,例如将所有元素乘 2:

1
2
3
doSomeThingOnArray([1, 2, 3]) { (element) -> Int in
return element * 2
}

然而代码写到这里,并不是一个很好的版本,因为这里的类型的信息是硬编码的,所以,我们来解决这个问题,并且将代码放到 Array 的 extension 中:

1
2
3
4
5
6
7
8
9
extension Array {
func map<T>(transform: Element -> T) -> [T] {
var result: [T] = []
for x in self {
result.append(transform(x))
}
return result
}
}

于是我们就可以像下面这样使用我们自己定义的 map:

1
2
3
[1, 2, 3].map { (x) -> Int in
return x + 1
}

当然,Swift 标准库中提供了 map 的实现,定义在 SequenceType 协议中。

参考资料 objc Functional Swift

如果这篇文章帮助您解决了问题,可以考虑请我喝杯咖啡