【问题标题】:Collections - extracting from an array of strings in a dictionary集合 - 从字典中的字符串数组中提取
【发布时间】:2015-10-02 20:05:23
【问题描述】:

我有大量采用以下形式的数据:[四个整数的数组],{与该整数数组有关的字符串集}。例如,

[1,1,1,8],{"(1+1+1)*8"}

[1,1,2,8],{"1*(1 + 2)*8","(1 + 2)/(1/8)"}

等等

我有数千个这样的对保存在一个外部文本文件中,并且需要能够根据密钥中的四个整数来调用各个行。一种解决方案似乎是在启动时将文本文件读入字典,但字典的明显公式

let myDict2:Dictionary<Array<Int>, Array <String>> = [[1,1,1,8]: ["(1+1+1)*8"],[1,1,2,8]: ["1*(1 + 2)*8","(1 + 2)/(1/8)"]]

失败,因为“类型 'Array' 不符合协议 'Hashable'。”

但我们可以将键从整数数组转换为字符串,并尝试这样:

let myDict2:Dictionary<String, Array <String>> = ["1118": ["(1+1+1)*8"],"1128": ["1*(1 + 2)*8","(1 + 2)/(1/8)"]]

没有错误,甚至看起来我们可以提取结果

let matches2=myDict2["1128"] // correctly returns ["1*(1 + 2)*8", "(1 + 2)/(1/8)"]

但是当我们尝试使用matches2[0] 从该答案中提取一个元素时,我们得到"Cannot subscript a value of type '[String]?'"

在我的键盘上随机敲击,我得到了这个与 matches2![0] 一起工作,但我不知道为什么。

  1. 有什么方法可以使我的原始字典尝试 [整数数组,字符串集] 工作吗?
  2. 在第二个公式 [string, set of strings] 中,为什么 matches2![0] 有效而 matches2[0] 无效?
  3. 字典是解决此问题的合理方法,还是有其他数据结构可以更好地实现我的目标?

【问题讨论】:

    标签: arrays dictionary collections swift2


    【解决方案1】:

    我先回答你的第二个问题:

    let matches2=myDict2["1128"] // returns an Optional<Array<String>>
    

    每个dict[key] 调用都会返回一个可选值,因为字典可能不包含该键。所以你必须先打开它

    matches2[0]  // error
    matches2![0] // ok
    

    现在谈谈您的其他问题:Dictionary 适用于您必须根据键保持数据唯一性的情况。例如,如果每个人都需要一个唯一的社会安全号码,则应将 SSN 用作字典键,并将人员信息用作其值。我不知道您的要求是什么,所以我将保持通用性。

    将四个数字连接成一个字符串是个坏主意,除非所有数字的位数相同。例如,(1,23,4,5)(12,3,4,5) 将生成相同的字符串。

    Array&lt;Int&gt; 没有实现Hashable 协议,因此您必须提供自己的包装器来实现。这是我的尝试:

    struct RowID : Hashable {
        var int1: Int
        var int2: Int
        var int3: Int
        var int4: Int
    
        init(_ int1: Int, _ int2: Int, _ int3: Int, _ int4: Int) {
            self.int1 = int1
            self.int2 = int2
            self.int3 = int3
            self.int4 = int4
        }
    
        var hashValue : Int {
            get {
                return "\(int1),\(int2),\(int3),\(int4)".hashValue
            }
        }
    }
    
    // Hashable also requires you to implement Equatable
    func ==(lhs: RowID, rhs: RowID) -> Bool {
        return lhs.int1 == rhs.int1
                && lhs.int2 == rhs.int2
                && lhs.int3 == rhs.int3
                && lhs.int4 == rhs.int4
    }
    
    let myDict: [RowID: [String]] = [
        RowID(1,1,1,8): ["(1+1+1)*8"],
        RowID(1,1,2,8): ["1*(1 + 2)*8","(1 + 2)/(1/8)"]
    ]
    
    let id = RowID(1,1,2,8)
    let value = myDict[id]![0]
    
    // You can also access it directly
    let value2 = myDict[RowID(1,1,1,8]]![0]
    

    【讨论】:

    • 由于 Integer 数组的约束,我知道如果转换为字符串形式,则不会有歧义。但是,您的 Hashable 和 Equatable 示例实现在将来肯定会派上用场。谢谢。
    猜你喜欢
    • 2020-12-30
    • 2023-01-13
    • 1970-01-01
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多