在 Swift 4.2 中,如何编写 func<() 来比较 class 中的 3 个字段?
In Swift 4.2, how do I write func<() to compare 3 fields in a class?
这是一个简单的 Swift class,有 3 个字段:
public class Cabbage: Comparable {
public let someString: String
public let someInt: Int
public let someDouble: Double
public init(_ someString: String, _ someInt: Int, _ someDouble: Double) {
self.someString = someString
self.someInt = someInt
self.someDouble = someDouble
}
public static func ==(lhs: Cabbage, rhs: Cabbage) -> Bool {
if lhs.someString == rhs.someString {
if lhs.someInt == rhs.someInt {
if lhs.someDouble == rhs.someDouble {
return true
}
}
}
return false
}
public static func <(lhs: Cabbage, rhs: Cabbage) -> Bool {
if lhs.someString < rhs.someString {
if lhs.someInt < rhs.someInt {
if lhs.someDouble < rhs.someDouble {
return true
}
}
}
return false
}
}
我认为我的第一个函数 func ==() 是正确的。当且仅当所有字段都相等时,我们 return 为真。
但我认为我的逻辑对于 func <() 是不正确的。
例如,如果 lhs.someString == rhs.someString,我是否应该比较 lhs.someInt 和 rhs.someInt?
如果这两个相等,我是否也应该比较 lhs.someDouble 和 rhs.someDouble?
如有任何想法或建议,我们将不胜感激。
是的,仅仅检查是否 lhs.someString < rhs.someString
是不够的。您还需要确定是否 lhs.someString > rhs.someString
(或 lhs.someString == rhs.someString
)。
正确写法有很多种。这是一个:
public static func <(lhs: Cabbage, rhs: Cabbage) -> Bool {
if lhs.someString < rhs.someString { return true }
if rhs.someString < lhs.someString { return false }
if lhs.someInt < rhs.someInt { return true }
if rhs.someInt < lhs.someInt { return false }
return lhs.someDouble < rhs.someDouble
}
更新
从Swift 2.2开始,标准库提供了最多六个元素的元组的比较运算符(如果所有元素都是Comparable
)。
此外,由于SE-0283,所有元组将很快(可能在Swift 5.3之后)符合Comparable
(如果它们的元素都符合Comparable
).
SE-0283 定义元组比较的方式如下:
Comparing a tuple to a tuple works elementwise:
Look at the first element, if they are equal move to the second element. Repeat until we find elements that are not equal and compare them.
此定义也适用于 Swift 2.2 中添加的现有元组比较运算符。也叫字典序.
所以我们可以使用元组比较为Cabbage
写一个更短版本的<
:
extension Cabbage: Comparable {
public static func <(lhs: Cabbage, rhs: Cabbage) -> Bool {
return (lhs.someString, lhs.someInt, lhs.someDouble)
< (rhs.someString, rhs.someInt, rhs.someDouble)
}
}
我们可以通过提取比较键的计算 属性 来减少代码重复。那么我们也可以用它来定义==
运算符。这就是我的意思:
extension Cabbage: Equatable, Comparable {
var comparisonKey: (String, Int, Double) {
return (someString, someInt, someDouble)
}
public static func ==(lhs: Cabbage, rhs: Cabbage) -> Bool {
return lhs.comparisonKey == rhs.comparisonKey
}
public static func <(lhs: Cabbage, rhs: Cabbage) -> Bool {
return lhs.comparisonKey < rhs.comparisonKey
}
}
这是一个简单的 Swift class,有 3 个字段:
public class Cabbage: Comparable {
public let someString: String
public let someInt: Int
public let someDouble: Double
public init(_ someString: String, _ someInt: Int, _ someDouble: Double) {
self.someString = someString
self.someInt = someInt
self.someDouble = someDouble
}
public static func ==(lhs: Cabbage, rhs: Cabbage) -> Bool {
if lhs.someString == rhs.someString {
if lhs.someInt == rhs.someInt {
if lhs.someDouble == rhs.someDouble {
return true
}
}
}
return false
}
public static func <(lhs: Cabbage, rhs: Cabbage) -> Bool {
if lhs.someString < rhs.someString {
if lhs.someInt < rhs.someInt {
if lhs.someDouble < rhs.someDouble {
return true
}
}
}
return false
}
}
我认为我的第一个函数 func ==() 是正确的。当且仅当所有字段都相等时,我们 return 为真。
但我认为我的逻辑对于 func <() 是不正确的。
例如,如果 lhs.someString == rhs.someString,我是否应该比较 lhs.someInt 和 rhs.someInt?
如果这两个相等,我是否也应该比较 lhs.someDouble 和 rhs.someDouble?
如有任何想法或建议,我们将不胜感激。
是的,仅仅检查是否 lhs.someString < rhs.someString
是不够的。您还需要确定是否 lhs.someString > rhs.someString
(或 lhs.someString == rhs.someString
)。
正确写法有很多种。这是一个:
public static func <(lhs: Cabbage, rhs: Cabbage) -> Bool {
if lhs.someString < rhs.someString { return true }
if rhs.someString < lhs.someString { return false }
if lhs.someInt < rhs.someInt { return true }
if rhs.someInt < lhs.someInt { return false }
return lhs.someDouble < rhs.someDouble
}
更新
从Swift 2.2开始,标准库提供了最多六个元素的元组的比较运算符(如果所有元素都是Comparable
)。
此外,由于SE-0283,所有元组将很快(可能在Swift 5.3之后)符合Comparable
(如果它们的元素都符合Comparable
).
SE-0283 定义元组比较的方式如下:
Comparing a tuple to a tuple works elementwise:
Look at the first element, if they are equal move to the second element. Repeat until we find elements that are not equal and compare them.
此定义也适用于 Swift 2.2 中添加的现有元组比较运算符。也叫字典序.
所以我们可以使用元组比较为Cabbage
写一个更短版本的<
:
extension Cabbage: Comparable {
public static func <(lhs: Cabbage, rhs: Cabbage) -> Bool {
return (lhs.someString, lhs.someInt, lhs.someDouble)
< (rhs.someString, rhs.someInt, rhs.someDouble)
}
}
我们可以通过提取比较键的计算 属性 来减少代码重复。那么我们也可以用它来定义==
运算符。这就是我的意思:
extension Cabbage: Equatable, Comparable {
var comparisonKey: (String, Int, Double) {
return (someString, someInt, someDouble)
}
public static func ==(lhs: Cabbage, rhs: Cabbage) -> Bool {
return lhs.comparisonKey == rhs.comparisonKey
}
public static func <(lhs: Cabbage, rhs: Cabbage) -> Bool {
return lhs.comparisonKey < rhs.comparisonKey
}
}