如何在Swift中比较两本词典?

时间:2022-12-13 23:05:31

Is there an easy way to compare two [String: AnyObject] dictionaries in swift, since it doesn't accept the == operator?

由于swift不接受==运算符,是否有一种简单的方法来比较两个[String: AnyObject]字典?

By comparing two dictionaries, I mean checking that they have the same exact keys and for every key they have the same values.

通过比较两个字典,我的意思是检查它们是否有相同的键,每个键的值都是相同的。

4 个解决方案

#1


77  

As already mentioned by Hot Licks you can use NSDictionary method isEqualToDictionary() to check if they are equal as follow:

正如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

you can also implement a custom operator "==" as follow:

您还可以实现自定义操作符“==”,如下所示:

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

Xcode 9•Swift 4

From the docs, dictionary is now defined as a struct:

从文档中,字典现在被定义为一个结构体:

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

Description

描述

A collection whose elements are key-value pairs. A dictionary is a type of hash table, providing fast access to the entries it contains. Each entry in the table is identified using its key, which is a hashable type such as a string or number. You use that key to retrieve the corresponding value, which can be any object. In other languages, similar data types are known as hashes or associated arrays. Create a new dictionary by using a dictionary literal. A dictionary literal is a comma-separated list of key-value pairs, in which a colon separates each key from its associated value, surrounded by square brackets. You can assign a dictionary literal to a variable or constant or pass it to a function that expects a dictionary.

元素是键值对的集合。字典是哈希表的一种类型,提供对它所包含的条目的快速访问。表中的每个条目都使用它的键进行标识,键是一种可清洗的类型,如字符串或数字。您可以使用该键来检索相应的值,该值可以是任何对象。在其他语言中,类似的数据类型称为散列或关联数组。使用字典字面量创建一个新字典。dictionary literal是一个以逗号分隔的键-值对列表,其中冒号将每个键与其关联的值分隔开,并由方括号括起来。您可以将字典字面量分配给变量或常量,或者将它传递给期望字典的函数。

Here’s how you would create a dictionary of HTTP response codes and their related messages:

下面是如何创建一个HTTP响应代码字典及其相关消息:

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

The responseMessages variable is inferred to have type [Int: String]. The Key type of the dictionary is Int, and the Value type of the dictionary is String.

responsemessage变量被推断为具有类型[Int: String]。字典的键类型是Int型,字典的值类型是String。

To create a dictionary with no key-value pairs, use an empty dictionary literal ([:]).

要创建一个没有键值对的字典,使用一个空字典文字([:])。

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

Any type that conforms to the Hashable protocol can be used as a dictionary’s Key type, including all of Swift’s basic types. You can use your own custom types as dictionary keys by making them conform to the Hashable protocol.

任何符合Hashable协议的类型都可以用作字典的键类型,包括Swift的所有基本类型。您可以使用您自己的自定义类型作为字典密钥,使它们符合Hashable协议。


We don't need to define a custom operator anymore:

我们不再需要定义自定义操作符:

From the docs:

从文档:

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

Testing:

测试:

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

In the example above all dictionary keys and values are the same type. If we try to compare two dictionaries of type [String: Any] Xcode will complain that Binary operator == cannot be applied to two [String: Any] operands.

在上面的示例中,所有的字典键和值都是相同的类型。如果我们尝试比较两个类型为[String: Any]的字典,Xcode会抱怨二进制运算符==不能应用于两个[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

But we can extend the == operator functionality implementing an infix operator, casting Swift Dictionary to NSDictionary and constraining the dictionary Value to Hashable Protocol:

但是我们可以扩展==运算符功能来实现中缀运算符,将Swift字典转换为NSDictionary并将字典值限制为Hashable协议:


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

Testing:

测试:

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

#2


11  

In Swift 2, when both Key and Value are Equatable, you can use == on the dictionary itself:

在Swift 2中,当键和值相等时,可以在字典本身上使用==:

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

And, NSObject is Equatable:

而且,NSObject Equatable:

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

In your case, if you are working with Obj-C objects that you want to compare using isEqual:, you can simply use NSObject as your value type (rather than AnyObject).

在您的示例中,如果您正在使用使用isEqual:比较的object - c对象,您可以简单地使用NSObject作为值类型(而不是AnyObject)。

#3


10  

Swift 4 Update:

Comparing Dictionaries is now native! (Docs here)

比较字典现在是本地语言!(文档)


Swift 3:

Leo Dabus already has an excellently written post with the accepted solution. However, for me, I found that it needed one more step to be fully usable. As you can see from his code, you need to set your dictionary type to [AnyHashable: Any], or otherwise you'll get Binary operator '==' cannot be applied to two '[String : Any]' operands, to use a dictionary common in deserializing JSON for my example.

里奥·达布斯已经写了一篇优秀的文章,介绍了公认的解决方案。然而,对我来说,我发现它需要再多一步才能完全使用。正如您从他的代码中可以看到的,您需要将字典类型设置为[AnyHashable: Any],否则您将得到二进制操作符'= '不能应用于两个'[String: Any]'操作数,以使用在我的示例中反序列化JSON时常见的字典。

Generics to the rescue!:

泛型来拯救!

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

or in another case I had, with [String: Any?]:

或者在另一种情况下,用[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)
}

#4


1  

Without custom type in value of Dictionary, in Swift 2+ you can use the == operator to compare two Dictionary to check if they are equal or not.

如果字典中没有自定义类型,在Swift 2+中,可以使用==操作符来比较两个字典,以检查它们是否相等。

But in some cases with custom types as the Dictionary's value (like struct), you must adopt Equatable in order for that custom type to use == operator.

但是,在某些情况下,自定义类型作为字典的值(例如struct),您必须采用Equatable,以便该自定义类型使用==操作符。

Ex:

例:

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

Now you can use the == operator to compare two dictionaries:

现在您可以使用==运算符来比较两个字典:

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

#1


77  

As already mentioned by Hot Licks you can use NSDictionary method isEqualToDictionary() to check if they are equal as follow:

正如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

you can also implement a custom operator "==" as follow:

您还可以实现自定义操作符“==”,如下所示:

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

Xcode 9•Swift 4

From the docs, dictionary is now defined as a struct:

从文档中,字典现在被定义为一个结构体:

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

Description

描述

A collection whose elements are key-value pairs. A dictionary is a type of hash table, providing fast access to the entries it contains. Each entry in the table is identified using its key, which is a hashable type such as a string or number. You use that key to retrieve the corresponding value, which can be any object. In other languages, similar data types are known as hashes or associated arrays. Create a new dictionary by using a dictionary literal. A dictionary literal is a comma-separated list of key-value pairs, in which a colon separates each key from its associated value, surrounded by square brackets. You can assign a dictionary literal to a variable or constant or pass it to a function that expects a dictionary.

元素是键值对的集合。字典是哈希表的一种类型,提供对它所包含的条目的快速访问。表中的每个条目都使用它的键进行标识,键是一种可清洗的类型,如字符串或数字。您可以使用该键来检索相应的值,该值可以是任何对象。在其他语言中,类似的数据类型称为散列或关联数组。使用字典字面量创建一个新字典。dictionary literal是一个以逗号分隔的键-值对列表,其中冒号将每个键与其关联的值分隔开,并由方括号括起来。您可以将字典字面量分配给变量或常量,或者将它传递给期望字典的函数。

Here’s how you would create a dictionary of HTTP response codes and their related messages:

下面是如何创建一个HTTP响应代码字典及其相关消息:

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

The responseMessages variable is inferred to have type [Int: String]. The Key type of the dictionary is Int, and the Value type of the dictionary is String.

responsemessage变量被推断为具有类型[Int: String]。字典的键类型是Int型,字典的值类型是String。

To create a dictionary with no key-value pairs, use an empty dictionary literal ([:]).

要创建一个没有键值对的字典,使用一个空字典文字([:])。

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

Any type that conforms to the Hashable protocol can be used as a dictionary’s Key type, including all of Swift’s basic types. You can use your own custom types as dictionary keys by making them conform to the Hashable protocol.

任何符合Hashable协议的类型都可以用作字典的键类型,包括Swift的所有基本类型。您可以使用您自己的自定义类型作为字典密钥,使它们符合Hashable协议。


We don't need to define a custom operator anymore:

我们不再需要定义自定义操作符:

From the docs:

从文档:

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

Testing:

测试:

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

In the example above all dictionary keys and values are the same type. If we try to compare two dictionaries of type [String: Any] Xcode will complain that Binary operator == cannot be applied to two [String: Any] operands.

在上面的示例中,所有的字典键和值都是相同的类型。如果我们尝试比较两个类型为[String: Any]的字典,Xcode会抱怨二进制运算符==不能应用于两个[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

But we can extend the == operator functionality implementing an infix operator, casting Swift Dictionary to NSDictionary and constraining the dictionary Value to Hashable Protocol:

但是我们可以扩展==运算符功能来实现中缀运算符,将Swift字典转换为NSDictionary并将字典值限制为Hashable协议:


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

Testing:

测试:

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

#2


11  

In Swift 2, when both Key and Value are Equatable, you can use == on the dictionary itself:

在Swift 2中,当键和值相等时,可以在字典本身上使用==:

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

And, NSObject is Equatable:

而且,NSObject Equatable:

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

In your case, if you are working with Obj-C objects that you want to compare using isEqual:, you can simply use NSObject as your value type (rather than AnyObject).

在您的示例中,如果您正在使用使用isEqual:比较的object - c对象,您可以简单地使用NSObject作为值类型(而不是AnyObject)。

#3


10  

Swift 4 Update:

Comparing Dictionaries is now native! (Docs here)

比较字典现在是本地语言!(文档)


Swift 3:

Leo Dabus already has an excellently written post with the accepted solution. However, for me, I found that it needed one more step to be fully usable. As you can see from his code, you need to set your dictionary type to [AnyHashable: Any], or otherwise you'll get Binary operator '==' cannot be applied to two '[String : Any]' operands, to use a dictionary common in deserializing JSON for my example.

里奥·达布斯已经写了一篇优秀的文章,介绍了公认的解决方案。然而,对我来说,我发现它需要再多一步才能完全使用。正如您从他的代码中可以看到的,您需要将字典类型设置为[AnyHashable: Any],否则您将得到二进制操作符'= '不能应用于两个'[String: Any]'操作数,以使用在我的示例中反序列化JSON时常见的字典。

Generics to the rescue!:

泛型来拯救!

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

or in another case I had, with [String: Any?]:

或者在另一种情况下,用[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)
}

#4


1  

Without custom type in value of Dictionary, in Swift 2+ you can use the == operator to compare two Dictionary to check if they are equal or not.

如果字典中没有自定义类型,在Swift 2+中,可以使用==操作符来比较两个字典,以检查它们是否相等。

But in some cases with custom types as the Dictionary's value (like struct), you must adopt Equatable in order for that custom type to use == operator.

但是,在某些情况下,自定义类型作为字典的值(例如struct),您必须采用Equatable,以便该自定义类型使用==操作符。

Ex:

例:

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

Now you can use the == operator to compare two dictionaries:

现在您可以使用==运算符来比较两个字典:

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