作为练习,我尝试将地图,长度和过滤器写为reduce函数。
func map<T>(array: [T], f: (T->T)) -> [T] {
return array.reduce([]) {
(var seed, value) in
seed.append(f(value))
return seed
}
}
func length<T>(array: [T]) -> Int {
return array.reduce(0){ (x,_) in x + 1 }
}
func filter<T>(array: [T], predicate: (T->Bool)) -> [T]{
return array.reduce([]){
(var seed, value) in
if predicate(value){
seed.append(value)
}
return seed
}
}
这是我可以用来将这些函数重写为reduce的最优雅的语法吗? 第二个问题:地图采用函数f:(T-> T) 基本上类型说我只能返回T类型的东西,但如果我写的函数将类型T转换为Bool,或者Int ... 我该如何做到这一点? 好像地图不存在
答案 0 :(得分:7)
对于将类型T
转换为(可能不同的)类型S
的映射
只需使用两个类型的占位符:
func map<T, S>(array: [T], f: (T->S)) -> [S] {
return array.reduce([]) {
(var seed, value) in
seed.append(f(value))
return seed
}
}
示例:
let x = map([1, 2, 3], f: { String($0) })
print(x) // ["1", "2", "3"]
这个“是否是最优雅的语法”也是一个
个人意见问题。如果您替换append()
方法
通过数组连接+
,然后seed
参数需要
不可变:
func map<T, S>(array: [T], f: (T->S)) -> [S] {
return array.reduce([]) {
(seed, value) in
seed + [f(value)]
}
}
可以使用简写参数名称
编写func map<T, S>(array: [T], f: (T->S)) -> [S] {
return array.reduce([]) { $0 + [ f($1) ] }
}
类似地:
func filter<T>(array: [T], predicate: (T->Bool)) -> [T]{
return array.reduce([]) { predicate($1) ? $0 + [ $1 ] : $0 }
}
请注意map()
和filter()
的实施使用
reduce()
(而不是循环)非常无效,因为在每个缩减步骤中都会创建新数组。参见例如
进行分析。对于练习(如你所说),这很好,只是 不要在生产中使用这样的东西。)
答案 1 :(得分:0)
扩展名CollectionType
extension CollectionType {
func MyMap<T>(transform: (Self.Generator.Element) -> T) -> [T] {
let list = self.reduce([T]()) { (var seed, value) in
seed.append(transform(value))
return seed
}
return list
}}
然后使用[1,2,3] .MyMap({$ 0 + 1})