web-dev-qa-db-ja.com

Swiftの2つの辞書を比較するにはどうすればよいですか?

[String: AnyObject]演算子を受け入れないため、Swiftの2つの==辞書を比較する簡単な方法はありますか?

2つの辞書を比較するということは、それらが正確に同じキーを持ち、すべてのキーに対して同じ値を持つことをチェックするということです。

61
bubakazouba

Hot Licksで既に述べたように、NSDictionaryメソッド isEqualToDictionary ()を使用して、次のように等しいかどうかを確認できます。

let dic1: [String: AnyObject] = ["key1": 100, "key2": 200]
let dic2: [String: AnyObject] = ["key1": 100, "key2": 200]
let dic3: [String: AnyObject] = ["key1": 100, "key2": 250]

println( NSDictionary(dictionary: dic1).isEqualToDictionary(dic2) )   // true
println( NSDictionary(dictionary: dic1).isEqualToDictionary(dic3) )  // false

次のようにカスタム演算子「==」を実装することもできます。

public func ==(lhs: [String: AnyObject], rhs: [String: AnyObject] ) -> Bool {
    return NSDictionary(dictionary: lhs).isEqualToDictionary(rhs)
}

println(dic1 == dic2)   // true
println(dic1 == dic3)   // false

Xcode 9•Swift 4

ドキュメントから、辞書は構造体として定義されるようになりました。

struct Dictionary<Key : Hashable, Value> : Collection, ExpressibleByDictionaryLiteral

説明

要素がキーと値のペアであるコレクション。辞書はハッシュテーブルの一種で、含まれるエントリへの高速アクセスを提供します。テーブル内の各エントリは、キーを使用して識別されます。キーは、文字列や数字などのハッシュ可能なタイプです。そのキーを使用して、対応する値(任意のオブジェクト)を取得します。他の言語では、同様のデータ型はハッシュまたは関連配列として知られています。辞書リテラルを使用して、新しい辞書を作成します。辞書リテラルは、キーと値のペアのカンマ区切りリストで、コロンは角括弧で囲まれた関連する値から各キーを区切ります。辞書リテラルを変数または定数に割り当てるか、辞書を必要とする関数に渡すことができます。

HTTP応答コードと関連メッセージの辞書を作成する方法は次のとおりです。

var responseMessages = [200: "OK",
                        403: "Access forbidden",
                        404: "File not found",
                        500: "Internal server error"]

ResponseMessages変数は、タイプ[Int: String]を持つと推測されます。辞書のキータイプはIntで、辞書の値タイプはStringです。

キーと値のペアを持たない辞書を作成するには、空の辞書リテラル([:])を使用します。

var emptyDict: [String: String] = [:]

Swiftのすべての基本タイプを含む、ハッシュ可能なプロトコルに準拠するタイプは、辞書のキータイプとして使用できます。 Hashableプロトコルに準拠させることにより、独自のカスタムタイプを辞書キーとして使用できます。


カスタム演算子を定義する必要はもうありません。

ドキュメントから:

static func ==(lhs: [Key : Value], rhs: [Key : Value]) -> Bool

テスト:

let dic1 = ["key1": 100, "key2": 200]
let dic2 = ["key1": 100, "key2": 200]
let dic3 = ["key1": 100, "key2": 250]

print(dic1 == dic2)   // true
print(dic1 == dic3)   // false

上記の例では、すべての辞書のキーと値は同じタイプです。タイプ[String: Any]の2つの辞書を比較しようとすると、Xcodeは2項演算子==を2つの[String: Any]オペランドに適用できないと文句を言います。

    let dic4: [String: Any] = ["key1": 100, "key2": "200"]
    let dic5: [String: Any] = ["key1": 100, "key2": "200"]
    let dic6: [String: Any] = ["key1": 100, "key2": Date()]

    print(dic4 == dic5)  // Binary operator == cannot be applied to two `[String: Any]` operands

ただし、Swift辞書をNSDictionaryにキャストし、辞書の値をハッシュ可能プロトコルに制限する、中置演算子を実装する==演算子機能を拡張できます。


public func ==<K, V: Hashable>(lhs: [K: V], rhs: [K: V] ) -> Bool {
    return (lhs as NSDictionary).isEqual(to: rhs)
}

テスト:

let dic4: [String: AnyHashable] = ["key1": 100, "key2": "200"]
let dic5: [String: AnyHashable] = ["key1": 100, "key2": "200"]
let dic6: [String: AnyHashable] = ["key1": 100, "key2": Date()]

print(dic4 == dic5)   // true
print(dic4 == dic6)   // false
96
Leo Dabus

Swift 4アップデート:

辞書の比較がネイティブになりました! (ドキュメント ここ


スウィフト3:

レオ・ダバスはすでに、受け入れられた解決策に関する素晴らしい記事を書いています。ただし、私にとっては、完全に使用するにはもう1つの手順が必要であることがわかりました。彼のコードからわかるように、辞書タイプを[AnyHashable: Any]に設定する必要があります。そうでない場合は、Binary operator '==' cannot be applied to two '[String : Any]' operandsを取得して、私の例のJSONの逆シリアル化で一般的な辞書を使用します。

救助のためのジェネリック!:

// Swift 3.0
func == <K, V>(left: [K:V], right: [K:V]) -> Bool {
    return NSDictionary(dictionary: left).isEqual(to: right)
}

または別の場合、[String: Any?]で:

func == <K, V>(left: [K:V?], right: [K:V?]) -> Bool {
    guard let left = left as? [K: V], let right = right as? [K: V] else { return false }
    return NSDictionary(dictionary: left).isEqual(to: right)
}
13
AmitaiB

Swift 2でKeyValueの両方Equatableの場合、辞書自体で==を使用できます。

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

そして、NSObjectはEquatableです:

public func ==(lhs: NSObject, rhs: NSObject) -> Bool

あなたの場合、isEqual:を使用して比較したいObj-Cオブジェクトを使用している場合は、NSObjectを(AnyObjectではなく)値型として使用できます。

11
jtbandes

辞書の値にカスタムタイプがない場合、Swift 2+では、==演算子を使用して2つのDictionaryを比較して、等しいかどうかを確認できます。

ただし、Dictionaryの値としてカスタム型(structなど)を使用する場合、そのカスタム型で==演算子を使用するには、Equatableを採用する必要があります。

例:

// custom type
struct Custom: Equatable {
    var value: Int
}

// MARK: adopting Equatable
func ==(lhs: Custom, rhs: Custom) -> Bool {
    if lhs.value == rhs.value {
        return true
    } else {
        return false
    }
}

これで、==演算子を使用して2つの辞書を比較できます。

let dic3: [String: Custom] = ["key1": Custom(value:1), "key2": Custom(value:2)]
let dic4: [String: Custom] = ["key1": Custom(value:1), "key2": Custom(value:2)]

if (dic3 == dic4) {
    print("equal")
} else {
    print("not equal")
}
0
larva