Swift Filter有一个更优雅的语法,带有2个参数

时间:2017-02-26 10:08:35

标签: swift

是否有更优雅的方法可以使用其他参数(或map,reduce)进行过滤。

当我使用单个参数进行过滤时,我们会得到一个漂亮易用的语法

let numbers = Array(1...10)

func isGreaterThan5(number:Int) -> Bool {
    return number > 5
}

numbers.filter(isGreaterThan5)

但是,如果我需要向我的函数传递一个额外的参数,那么结果很难看

func isGreaterThanX(number:Int,x:Int) -> Bool {
    return number > x
}

numbers.filter { (number) -> Bool in
    isGreaterThanX(number: number, x: 8)
}

我想使用像

这样的东西
numbers.filter(isGreaterThanX(number: $0, x: 3))

但是这给出了一个未包含在闭包

中的编译错误匿名闭包参数

1 个答案:

答案 0 :(得分:8)

你可以改变你的函数来返回一个服务的闭包 作为过滤方法的谓词:

func isGreaterThan(_ lowerBound: Int) -> (Int) -> Bool {
    return { $0 > lowerBound }
}

let filtered = numbers.filter(isGreaterThan(5))

isGreaterThan是一个带有Int参数并返回的函数 类型为(Int) -> Bool的闭包。返回的关闭"捕获" 给定下界的值。

如果你使函数通用,那么它可以用于 其他类似的类型:

func isGreaterThan<T: Comparable>(_ lowerBound: T) -> (T) -> Bool {
    return { $0 > lowerBound }
}

print(["D", "C", "B", "A"].filter(isGreaterThan("B")))

在这种特殊情况下,文字闭包也很容易理解:

let filtered = numbers.filter( { $0 > 5 })

只是为了完整性:使用这个事实 Instance Methods are Curried Functions in Swift,这也可行:

extension Comparable {
    func greaterThanFilter(value: Self) -> Bool {
        return value > self
    }
}

let filtered = numbers.filter(5.greaterThanFilter)

但&#34;逆转逻辑&#34;可能会令人困惑。

备注:在早期的Swift版本中,您可以使用curried函数 语法:

func isGreaterThan(lowerBound: Int)(value: Int) -> Bool {
    return  value > lowerBound
}

但此功能已removed in Swift 3.