【问题标题】:Swift Dictionary of string's array equality字符串数组相等的Swift字典
【发布时间】:2016-06-07 16:41:06
【问题描述】:

我正在尝试拥有一个字典,其中字符串作为键,字符串数组作为值。
然后我想检查其中两个字典是否相等:

let dicOfStringStringAr1: [String : [String]] = ["key1" : ["val", "for key 1"]]
let dicOfStringStringAr2: [String : [String]] = ["key1" : ["val", "for key 1"]]
if dicOfStringStringAr1 == dicOfStringStringAr2 {
    print("Dictionary of String Array")
}

但我得到这个错误:

错误:二元运算符 '==' 不能应用于两个 '[String : [String]]' 操作数

但是如果值是 String 而不是 [String] 它可以工作。

let dicOfStringAr1: [String : String] = ["key1" : "val"]
let dicOfStringAr2: [String : String] = ["key1" : "val"]
if dicOfStringAr1 == dicOfStringAr2 {
    print("Dictionary of String Array")
}

我不明白这个问题。
有人可以解释是什么问题。


查看 Dictionary 的默认 == Swift 函数后

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

我意识到没有将值表示为数组的定义,并且“通用”值无法解析为集合。 (不知道为什么)。
所以我做了一个 == 函数,它有 [Key : [Value]] 参数。现在代码可以工作了。

@warn_unused_result
public func ==<Key : Equatable, Value : Equatable>(lhs: [Key : [Value]], rhs: [Key : [Value]]) -> Bool {
    var result = lhs.count == rhs.count
    for (k, v) in lhs {
        guard let arValue = rhs[k] where result == true else {
            result = false
            break
        }

        result = v == arValue
    }

    return result
}

有人可以解释为什么在 Swift == 实现中 Value 不能解析为单个项目,即一个数组吗?

【问题讨论】:

    标签: arrays swift dictionary equality


    【解决方案1】:

    这实际上是有道理的。从&lt;Key : Equatable, Value : Equatable&gt; 类型的== 函数可以看出,它要求Value 符合Equatable。默认情况下,Array 类型不符合 Equatable注意,这并不意味着您不能使用 == 比较两个数组。

    [1, 2, 3] == ["a", "b", "c"] // false.
    

    符合Equatable 意味着您可以使用==,但反之则不行。

    您当然可以扩展Array 类型以符合Equatable

    extension Array: Equatable {}
    // Implement the following method.
    public func ==<T: CollectionType, U: CollectionType>(lhs: T, rhs: U) -> Bool {}
    

    更新

    我想说现在不可能为Array 实现一个合理的==。 (可能在future swift version

    对于您的具体情况,我会说以下方法足够公平。当您有自定义 struct 时,只需确保它符合 Equatable

    public func  ==<Key : Equatable, Value : CollectionType where Value.Generator.Element: Equatable>(lhs: [Key : Value], rhs: [Key : Value]) -> Bool {
        guard lhs.keys.elementsEqual(rhs.keys) else { return false }
    
        for (key, value) in lhs {
            if !value.elementsEqual(rhs[key]!) { return false }
        }
    
        return true
    }
    

    例如:

    struct Number: Equatable {
        var x: Int
        var y: Int
    }
    
    func ==(lhs: Number, rhs: Number) -> Bool {
        return lhs.x == rhs.x && lhs.y == rhs.y
    }
    
    let dicOfStringStringAr1: [String : [Number]] = ["key1" : [Number(x: 1, y: 2), Number(x: 1, y: 2)]]
    let dicOfStringStringAr2: [String : [Number]] = ["key1" : [Number(x: 1, y: 2), Number(x: 1, y: 2)]]
    if dicOfStringStringAr1 == dicOfStringStringAr2 {
        print("Dictionary of String Array") // "Dictionary of String Array"
    }
    

    【讨论】:

    • 有趣的想法,您将如何实现您的 == 函数以实现通用和类型安全。我已经尝试==&lt;T: CollectionType, U: CollectionType where T.Generator.Element: Equatable, T.Generator.Element == U.Generator.Element&gt; 将函数的范围限制为仅可以与 == 比较的数组,但还必须具有==&lt;T: CollectionType, U: CollectionType&gt; 以符合协议。问题是最后一个是使用所以我总是假的。
    • 稍后我将发布另一个关于此的问题,以探索以通用方式工作的可能性。如果您对此有任何想法,我会在完成后发表新评论。
    • 谢谢,这不像我希望的那样通用,但它的工作方式比我的解决方案更广泛。作为一个例子,我无法让它与这个字典 [String : [String : String]] 结构一起工作。
    • 再次感谢,但是我遇到了这个实现的问题,它使 2 Set Ambiguous...
    【解决方案2】:

    幸运的是,您可以通过将字典转换为 NSDictionary 并使用其方法 isEqualToDictionary 来检查这些字典是否相等。例如:

    if NSDictionary(dictionary: dicOfStringStringAr1).isEqualToDictionary(dicOfStringStringAr2) {
        print("Dictionary of String Array")
    }
    

    【讨论】:

    • 这是一个仅适用于对象的漫游,如果我有一个结构数组,则此代码将中断。我正在寻找更通用的解决方案。
    • 这将是您提出问题的有用信息
    • 谢谢,但我坚持认为“有人对问题所在有所了解。”明确表示我对理解这个问题比四处走走更感兴趣。我已经更新了这个问题。我希望它能消除歧义。
    • 我想我读过一些关于 matt 的文章,说这是因为它会自动桥接到 NSString 等。但如果你想确定,你可以深入研究他的 cmets 或他拥有的帖子回答了几次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-10
    相关资源
    最近更新 更多