2015-10-27 6 views
9

Warum kompiliert die letzte Anweisung nicht mit dem Fehler: Binary operator '==' cannot be applied to two '[[Simple]]’ operands, und gibt es eine Möglichkeit, die Simple Struktur zu ändern oder den Operator == zu erweitern, um Gleichheitsprüfungen für verschachtelte Arrays (oder Wörterbücher)?Swift-Gleichheitsoperator auf geschachtelten Arrays

var i1: [Int] = [1] 
var i2: [Int] = [1] 
i1 == i2 // -> true 


var i3: [[Int]] = [[1], [2]] 
var i4: [[Int]] = [[1], [2]] 
i3 == i4 // -> true 


struct Simple: Equatable, Hashable { 
    let message: String 

    var hashValue: Int { 
     return message.hashValue 
    } 
} 
func ==(lhs: Simple, rhs: Simple) -> Bool { 
    return lhs.message == rhs.message 
} 

var a: [Simple] = [Simple(message: "a")] 
var b: [Simple] = [Simple(message: "a")] 
a == b // -> true 

var x: [[Simple]] = [[Simple(message: "a")], [Simple(message: "b")]] 
var y: [[Simple]] = [[Simple(message: "a")], [Simple(message: "b")]] 
x == y // -> ERROR! Binary operator '==' cannot be applied to two '[[Simple]]’ operands 

Antwort

14

Der Grund wie in Why is Equatable not defined for optional arrays ähnlich ist. Arrays können mit == verglichen werden, wenn der Elementtyp Equatable ist:

/// Returns true if these arrays contain the same elements. 
public func ==<Element : Equatable>(lhs: [Element], rhs: [Element]) -> Bool 

, deshalb,

var a: [Simple] = [Simple(message: "a")] 
var b: [Simple] = [Simple(message: "a")] 
a == b // -> true 

compiliert.

Aber auch für gleichzusetzen Typen T, Array<T>nicht zum Equatable Protokoll nicht entspricht, zu vergleichen Why can't I make Array conform to Equatable?. Daher wird in

var x: [[Simple]] = [[Simple(message: "a")], [Simple(message: "b")]] 
var y: [[Simple]] = [[Simple(message: "a")], [Simple(message: "b")]] 
x == y // -> ERROR! Binary operator '==' cannot be applied to two '[[Simple]]’ operands 

x und y sind Arrays mit dem Elementtyp [Simple] die tut nicht dem Protokoll Equatable entsprechen, und es gibt keine passenden == Operator.

Sie könnten einen generischen == Operator einfach verschachtelte Arrays als

func ==<Element : Equatable> (lhs: [[Element]], rhs: [[Element]]) -> Bool { 
    return lhs.count == rhs.count && !zip(lhs, rhs).contains {$0 != $1 } 
} 

oder einfacher (wie von @kennytm vorgeschlagen) definieren:

func ==<Element : Equatable> (lhs: [[Element]], rhs: [[Element]]) -> Bool { 
    return lhs.elementsEqual(rhs, by: ==) 
} 

Dies macht x == y Kompilierung und Arbeit wie erwartet. Zurzeit scheint es keine Möglichkeit zu sein, einen == Operator auf beliebig verschachtelten Arrays zu definieren.

Hinweise:

  • Ab Swift 4.1 (derzeit in der Entwicklung, snapshots available):

    The standard library types Optional, Array, and Dictionary now conform to the Equatable protocol when their element types conform to Equatable. ...

    (vom Swift CHANGELOG). Das macht die obige Problemumgehung obsolet.

  • Allgemeine bedingte Konformität, wie in SE-0143 Conditional conformances, vorgeschlagen, wurde noch nicht implementiert.

+0

Vielleicht aktualisieren Sie die Implementierung zu 'LHs.ElementsEqual (rhs, von: ==)'? – kennytm

+0

@kennytm: Guter Vorschlag, danke! –

+0

Vorschlag: seit https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md wurde nicht in Swift 4 enthalten, aktualisieren Sie die Antwort –

1

Sie können es tun, indem Sie eine == Funktion für ihre Durchführung, wie folgt vor:

func == (lhs: [[Simple]], rhs: [[Simple]]) -> Bool { 
    //your code 
} 
+0

Entschuldigung für die Down-Abstimmung, aber diese Frage ist viel komplizierter als was Ihre Antwort impliziert. – Jeff

+0

@Jeff Sie haben ein Recht auf Ihre Meinung, aber ich bevorzuge immer einfache Lösungen gegenüber komplizierten. [YAGNI] (https://en.wikipedia.org/wiki/You_aren't_gonna_need_it) gilt hier. – Adam

+0

In meinem Kommentar ging es nicht darum, eine unnötig komplexe Antwort zu bevorzugen. Ihre Antwort ist keine Lösung für diese Frage. Deine Antwort ist unvollständig. Die Frage ist komplexer, als Sie zu verstehen scheinen. – Jeff

Verwandte Themen