web-dev-qa-db-ja.com

二項演算子 '=='は2つのオペランドに適用できません

プロトコルEquatableを持つクラスがあります。クラスは次のようになります。

class Item: Equatable {

    let item: [[Modifications: String]]

    init(item: [[Modifications: String]]) {
        self.item = item
    }
}

func ==(lhs: Item, rhs: Item) -> Bool {
    return lhs.item == rhs.item
}

しかし、これは私にエラーを与えています(タイトルを参照)。プロパティitem[[String: String]]以前、問題はなく、これを修正する方法がわかりません。私はグーグルで検索してみましたSOしかし運がなかった..

列挙型は単純な基本的なものです:

enum Modifications: Int {
    case Add    = 1
    case Remove = 2
    case More   = 3
    case Less   = 4
}
17
Henny Lee

Update:SE-0143条件付き適合 は、Swift 4.2で実装されました。

結果として、コードはすぐにコンパイルされます。 Itemstructとして定義すると

struct Item: Equatable {
    let item: [[Modifications: String]]

    init(item: [[Modifications: String]]) {
        self.item = item
    }
}

次に、コンパイラは==演算子を自動的に合成し、比較します SE-0185 EquatableおよびHashable準拠の合成


(Pre Swift 4.1 answer:)

問題は、==が辞書タイプ[Modifications: String]に定義されていても、そのタイプはEquatableに準拠していないことです。したがって、配列比較演算子

public func ==<Element : Equatable>(lhs: [Element], rhs: [Element]) -> Bool

[[Modifications: String]]に適用できません。

Item==の可能な簡潔な実装は

func ==(lhs: Item, rhs: Item) -> Bool {
    return lhs.item.count == rhs.item.count 
           && !Zip(lhs.item, rhs.item).contains {$0 != $1 }
}

@ user3441734が正しく述べているように、Foundationフレームワークがインポートされた場合、コードは[[String: String]]にコンパイルされます。これは、[String: String]NSDictionaryに準拠するEquatableに自動的に変換されるためです。その主張の「証拠」は次のとおりです。

func foo<T : Equatable>(obj :[T]) {
    print(obj.dynamicType)
}

// This does not compile:
foo( [[Modifications: String]]() )

// This compiles, and the output is "Array<NSDictionary>":
foo( [[String: String]]() )
19
Martin R

Itemオブジェクトの_==_関数では、2種類の辞書配列(具体的には、2種類の_[[Modifications: String]]_)を比較する方法をさらに指定する必要があります。

次の作業ソリューションでは、item配列の要素を要素ごと(辞書ごとの辞書)に比較し、_==_は配列に同じ数の辞書が含まれ、すべてのエントリが同じ場合にのみtrueを返しますdictionaresの配列で同じ方法で注文した

_func ==(lhs: Item, rhs: Item) -> Bool {

    if lhs.item.count == rhs.item.count {
        for (i, lhsDict) in lhs.item.enumerate() {
            if lhsDict != rhs.item[i] {
                return false
            }
        }
        return true
    }
    else {
        return false
    }
}

class Item : Equatable {

    let item: [[Modifications: String]]

    init(item: [[Modifications: String]]) {
        self.item = item
    }
}
_

あなたはおそらくこれを比較のために実際に使いたい形に修正したいと思うでしょうが、私はあなたがそれの要点を得ることを望みます。

また、プレイグラウンドでこれをテストする場合、_==_関数定義func ==(lhs: Item, rhs: Item) -> Bool { ..precedeクラス定義であることが重要であることに注意してください。 Equatableに。

3
dfri