Сопоставимое расширение работает, но дает плохие результаты - PullRequest
0 голосов
/ 23 мая 2018

Я написал сопоставимое расширение для массива:

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

, список выглядит хорошо, Tuplefunc < (lhs: Array<Element>, rhs: Array<Element>) вызывается и странные результаты:

неправильно, 100> 55:

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

неправильно, 100> 0:

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

хмм, ОК ..100> 55

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

ОК, -100 <55 </p>

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

ОК, -100 <0 </p>

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

ОК, -100 <100 </p>

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

Где может быть ошибка?

1 Ответ

0 голосов
/ 23 мая 2018

Ваша функция сравнения массивов недопустима, она не обеспечивает «строгий слабый порядок» :

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
...