[String: AnyObject]
演算子を受け入れないため、Swiftの2つの==
辞書を比較する簡単な方法はありますか?
2つの辞書を比較するということは、それらが正確に同じキーを持ち、すべてのキーに対して同じ値を持つことをチェックするということです。
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
辞書の比較がネイティブになりました! (ドキュメント ここ )
レオ・ダバスはすでに、受け入れられた解決策に関する素晴らしい記事を書いています。ただし、私にとっては、完全に使用するにはもう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)
}
Swift 2でKey
とValue
の両方が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ではなく)値型として使用できます。
辞書の値にカスタムタイプがない場合、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")
}