IT Share you

Swift에서 두 사전을 어떻게 비교합니까?

shareyou 2020. 11. 30. 20:18
반응형

Swift에서 두 사전을 어떻게 비교합니까?


연산자를 [String: AnyObject]받아들이지 않기 때문에 사전을 신속하게 비교할 수있는 쉬운 방법이 ==있습니까?

두 딕셔너리를 비교함으로써 정확히 동일한 키를 가지고 있고 모든 키에 대해 동일한 값을 가지고 있는지 확인하는 것을 의미합니다.


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 프로토콜을 준수하는 모든 유형을 사전의 키 유형으로 사용할 수 있습니다. 고유 한 사용자 정의 유형을 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]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:


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

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.

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?]:

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

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

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

And, NSObject is 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).


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.

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.

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

참고URL : https://stackoverflow.com/questions/32365654/how-do-i-compare-two-dictionaries-in-swift

반응형