2015-10-02 4 views
0

У меня есть большой массив данных, который принимает следующий вид: [Array of four integers], {Набор строк, относящихся к этому массиву целых чисел}. Например,Коллекции - извлечение из массива строк в словаре

[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)"]] 

терпит неудачу, потому что «Тип„Массив“не соответствует протоколу„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]?'"

ударяться случайно на моей клавиатуре, я получил это вр k с matches2![0], но я понятия не имею, почему.

  1. Есть ли способ сделать мою первоначальную попытку словаря [array of ints, set of strings] работать?
  2. Во второй формулировке [строка, набор строк], Почему matches2![0] работы и matches2[0] нет?
  3. Является ли словарь разумным подходом к этому, или есть какая-то другая структура данных, которая может лучше выполнить мою цель?

ответ

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<Int> не реализует протокол 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] 
+0

Из-за ограничений на массив Integer, я знаю, что нет двусмысленных записей, если они преобразуются в строковые формы. Тем не менее, ваши примеры реализации Hashable и Equatable наверняка пригодится в будущем. Спасибо. –

Смежные вопросы