Swift: 在功能上使用 not 运算符
Swift: use not operator functionally
我想使用点语法得到布尔值的相反值。
例如
let digitsExceptForFive = [1, 2, 3, 4, 6, 7, 8, 9]
let fives = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter(!digitsExceptForFive.contains)
// Cannot convert value of type '(Int) -> Bool' to expected argument type 'Bool'
但是,以下代码有效。
let digitsExceptForFive = [1, 2, 3, 4, 6, 7, 8, 9]
let notFives = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter(digitsExceptForFive.contains)
// [1, 2, 3, 4, 6, 7, 8, 9]
我需要使用 not 运算符在功能上获得相反的值。如果可能的话,我不想为此定义布尔扩展或自定义运算符。
如何在 Swift 中做到这一点?
我猜你想写类似 digitsExceptForFive.contains.not
的东西。
遗憾的是,您不能,因为这需要类型 (Int) -> Bool
具有 not
方法。函数不能有方法。
您可以编写运算符 !
的重载来执行此操作(让您的第一次尝试成功),但我不推荐这样做。运算符重载往往会减慢编译时间并使后来的代码读者感到困惑。
我建议你这样写:
let fives = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter { !digitsExceptForFive.contains([=10=]) }
我只想将 Sequence
协议约束 Element
扩展到 Equatable
并实施 notContains
方法:
extension Sequence where Element: Equatable {
func notContains(_ element: Element) -> Bool { !contains(element) }
}
let digitsExceptForFive = [1, 2, 3, 4, 6, 7, 8, 9]
let fives = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter(digitsExceptForFive.notContains) // [5]
您还可以扩展 Bool and
提供 negated
属性,这将允许使用否定的 KeyPath
语法:
extension Bool {
var negated: Bool { !self }
}
let string = "abc12345"
let nonDigits = string.filter(\.isWholeNumber.negated) // "abc"
如果你真的想实现自定义前缀运算符(我真的更喜欢使用 notConstains 方法和 Bool 否定实例 属性)你可以这样做:
prefix func !<T>(predicate: @escaping (T) -> Bool) -> (T) -> Bool { { !predicate([=14=]) } }
用法:
let string = "abc12345"
let nonDigits = string.filter(!\.isWholeNumber) // "abc"
let digitsExceptForFive = [1, 2, 3, 4, 6, 7, 8, 9]
let fives = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter(!digitsExceptForFive.contains) // [5]
需要将此语言支持添加到 Swift 以符合人体工程学语义。请参考evolution pitch discussion on the Swift Evolution forums.
我想使用点语法得到布尔值的相反值。
例如
let digitsExceptForFive = [1, 2, 3, 4, 6, 7, 8, 9]
let fives = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter(!digitsExceptForFive.contains)
// Cannot convert value of type '(Int) -> Bool' to expected argument type 'Bool'
但是,以下代码有效。
let digitsExceptForFive = [1, 2, 3, 4, 6, 7, 8, 9]
let notFives = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter(digitsExceptForFive.contains)
// [1, 2, 3, 4, 6, 7, 8, 9]
我需要使用 not 运算符在功能上获得相反的值。如果可能的话,我不想为此定义布尔扩展或自定义运算符。
如何在 Swift 中做到这一点?
我猜你想写类似 digitsExceptForFive.contains.not
的东西。
遗憾的是,您不能,因为这需要类型 (Int) -> Bool
具有 not
方法。函数不能有方法。
您可以编写运算符 !
的重载来执行此操作(让您的第一次尝试成功),但我不推荐这样做。运算符重载往往会减慢编译时间并使后来的代码读者感到困惑。
我建议你这样写:
let fives = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter { !digitsExceptForFive.contains([=10=]) }
我只想将 Sequence
协议约束 Element
扩展到 Equatable
并实施 notContains
方法:
extension Sequence where Element: Equatable {
func notContains(_ element: Element) -> Bool { !contains(element) }
}
let digitsExceptForFive = [1, 2, 3, 4, 6, 7, 8, 9]
let fives = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter(digitsExceptForFive.notContains) // [5]
您还可以扩展 Bool and
提供 negated
属性,这将允许使用否定的 KeyPath
语法:
extension Bool {
var negated: Bool { !self }
}
let string = "abc12345"
let nonDigits = string.filter(\.isWholeNumber.negated) // "abc"
如果你真的想实现自定义前缀运算符(我真的更喜欢使用 notConstains 方法和 Bool 否定实例 属性)你可以这样做:
prefix func !<T>(predicate: @escaping (T) -> Bool) -> (T) -> Bool { { !predicate([=14=]) } }
用法:
let string = "abc12345"
let nonDigits = string.filter(!\.isWholeNumber) // "abc"
let digitsExceptForFive = [1, 2, 3, 4, 6, 7, 8, 9]
let fives = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter(!digitsExceptForFive.contains) // [5]
需要将此语言支持添加到 Swift 以符合人体工程学语义。请参考evolution pitch discussion on the Swift Evolution forums.