【问题标题】:Swift writing map, length, filter as reduceSwift编写map,length,filter为reduce
【发布时间】:2015-12-18 19:32:32
【问题描述】:

作为练习,我尝试将 map、length 和 filter 编写为 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 的最优雅的语法吗? 第二个问题:map 接受一个函数 f:(T->T) 基本上类型说我只能返回 T 类型的东西,但是如果我编写的函数将 T 类型转换为 Bool 或 Int... 我该如何做到这一点? 好像地图不存在

【问题讨论】:

    标签: swift function


    【解决方案1】:

    对于将类型 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()(而不是循环)非常无效,因为在每个缩减步骤中都会创建一个 新数组。参见示例

    进行分析。对于 exercise(如您所说),这很好,只是 不要在生产中使用这样的东西)。

    【讨论】:

    • 非常感谢,谢谢!正是我正在寻找的那种反馈。 Swift 一开始是一片陌生的风景;)
    • 奇怪的风景启发了你尝试这个!?! :)
    • 显然确实存在诸如传感器之类的东西 ;) 获得一些关于 swift 的基本知识的好方法。
    • 无论如何要实现没有reduce 的地图?
    • @HienQuangTran: let filtered = animals.filter { $0.characters.count == 3 }.
    【解决方案2】:

    扩展集合类型

    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})

    【讨论】:

      猜你喜欢
      • 2017-08-23
      • 1970-01-01
      • 2021-06-06
      • 2017-11-05
      • 1970-01-01
      • 1970-01-01
      • 2020-09-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多