可比扩展有效但效果不佳

时间:2018-05-23 12:29:11

标签: arrays swift sorting

我为Array编写了Comparable扩展名:

extension Array:Comparable where Element == Double {
     public static func < (lhs: Array<Element>, rhs: Array<Element>) -> Bool {
         let count = Swift.min(lhs.count, rhs.count)
         for i in 0..<count {
             if lhs[i] < rhs[i]  { return true }
        }
        return false
    }
}

和Tuple类:

extension Tuple:Comparable where T == Double {
    static func < (lhs: Tuple<T>, rhs: Tuple<T>) -> Bool {
        print ("compare \(lhs) \( lhs.content < rhs.content ? "<" : ">=") \(rhs)")
        return lhs.content < rhs.content
    }
}

当我打电话

return Array<This>(newVertices.sorted(by: { $0.position < $1.position}))

列表看起来不错,Tuple func < (lhs: Array<Element>, rhs: Array<Element>)被调用并且结果很奇怪:

错误,100&gt; 55:

compare Tuple<Double> 3-D: [100.0, 0.0, 55.0, ] < Tuple<Double> 3-D: [55.0, 55.0, 300.0, ]

错误,100&gt; 0:

compare Tuple<Double> 3-D: [100.0, 0.0, 55.0, ] < Tuple<Double> 3-D: [0.0, 55.0, 300.0, ]
嗯,好的...... 100&gt; 55

compare Tuple<Double> 3-D: [100.0, 0.0, 55.0, ] >= Tuple<Double> 3-D: [55.0, 0.0, 55.0, ]

好的,-100&lt; 55

compare Tuple<Double> 3-D: [-100.0, 55.0, 300.0, ] < Tuple<Double> 3-D: [55.0, 55.0, 300.0, ]

好的,-100&lt; 0

compare Tuple<Double> 3-D: [-100.0, 55.0, 300.0, ] < Tuple<Double> 3-D: [0.0, 55.0, 300.0, ]

好的,-100&lt; 100

compare Tuple<Double> 3-D: [-100.0, 55.0, 300.0, ] < Tuple<Double> 3-D: [100.0, 0.0, 55.0, ]

哪里可能是个错误?

1 个答案:

答案 0 :(得分:2)

你的数组比较功能无效,是不提供的 “strict weak ordering”

let a = [2.0, 1.0, 3.0]
let b = [1.0, 2.0, 4.0]

print(a < b) // true
print(b < a) // true

对于词典排序,您必须尽快返回false lhs[i] > rhs[i]用于某个索引,而不是继续循环。 一个阵列是另一个阵列的前缀的情况也不是 处理。

这将是一个正确的实施:

extension Array: Comparable where Element == Double {
    public static func < (lhs: Array<Element>, rhs: Array<Element>) -> Bool {
        let count = Swift.min(lhs.count, rhs.count)
        for i in 0..<count {
            if lhs[i] < rhs[i]  { return true }
            if lhs[i] > rhs[i]  { return false }
        }
        return lhs.count < rhs.count
    }
}

可以简化并推广到

extension Array: Comparable where Element: Comparable {
    public static func < (lhs: Array<Element>, rhs: Array<Element>) -> Bool {
        for (l, r) in zip(lhs, rhs) {
            if l < r { return true }
            if l > r { return false }
        }
        return lhs.count < rhs.count
    }
}

示例:

print( [2.0, 1.0, 3.0] < [1.0, 2.0, 4.0]) // false
print( [1.0, 2.0, 4.0] < [2.0, 1.0, 3.0]) // true
print( [1.0] < [1.0, 2.0]) // true
print( [1.0, 2.0] < [1.0, 2.0]) // false
print( [1.0, 2.0] < [1.0]) // false