2016-05-30 4 views
-1

Я бы хотел создать словарь словарей. В Swift как объявить словарь с ключом String и значением словаря такого же типа? Мне нужно иметь потенциально бесконечные гнезда. (. Вроде как построение дерева с использованием узлов Кроме это не дерево, это словарь.)Словарь словарей в Swift

Я попытался с помощью AnyObject, но получаю ошибку преобразования:

var node1: Dictionary<String, AnyObject?> = ["foo" : nil] 
var node2: Dictionary<String, AnyObject?> = ["bar" : node1] // ERROR: Cannot convert value of type 'Dictionary<String, AnyObject?>' (aka 'Dictionary<String, Optional<AnyObject>>') to expected dictionary value type 'Optional<AnyObject>' 

Есть ли тип-безопасный способ (т. е. не использовать AnyObject?)

+2

После скольких словарей оно заканчивается? Или это словари на всем пути? – overactor

+0

Да, это бесконечно. – Daniel

+1

Уверенный, имеющий бесконечное гнездо словарей, означает, что вы никогда не храните никаких данных? Поскольку у вас будет строка для ключа, а затем другой словарь в качестве значения. Вы никогда не будете хранить ничего, кроме ключей. Я думаю, что, возможно, другая структура данных будет лучше подходит. Чего вы пытаетесь достичь? – Welton122

ответ

4

Вы можете добиться чего-то вроде этого с помощью хорошего API и быстро набрать безопасность при использовании структуры и перечисления.

enum RecursiveDictValue<KeyType: Hashable, ValueType> { 
    case Value(ValueType) 
    case Dict(RecursiveDict<KeyType, ValueType>) 
} 

struct RecursiveDict<KeyType: Hashable, ValueType> { 
    typealias OwnType = RecursiveDict<KeyType, ValueType> 

    private var dict: [KeyType: RecursiveDictValue<KeyType, ValueType>] 

    init() { 
     dict = [:] 
    } 

    init(dict: [KeyType: RecursiveDictValue<KeyType, ValueType>]) { 
     self.dict = dict 
    } 

    // this ensures that we can safely chain subscripts 
    subscript(key: KeyType) -> OwnType { 
     get { 
      switch dict[key] { 
      case let .Dict(dict)?: 
       return dict 
      default: 
       return RecursiveDict<KeyType, ValueType>() 
      } 
     } 

     set(newValue) { 
      dict[key] = .Dict(newValue) 
     } 
    } 

    subscript(key: KeyType) -> ValueType? { 
     get { 
      switch dict[key] { 
      case let .Value(value)?: 
       return value 
      default: 
       return nil 
      } 
     } 

     set(newValue) { 
      if let newValue = newValue { 
       dict[key] = RecursiveDictValue<KeyType, ValueType>.Value(newValue) 
      } else { 
       dict[key] = nil 
      } 
     } 
    } 
} 

Это работает довольно хорошо (обратите внимание, что вам нужно, чтобы помочь быстры с типами, хотя):

var dict = RecursiveDict<String, Int>(dict: ["value":.Value(1), 
              "dict":.Dict(RecursiveDict<String, Int>(dict: ["nestedValue": .Value(2)]))]) 

if let value: Int = dict["value"] { 
    print(value) // prints 1 
} 

if let value: Int = dict["dict"]["nestedValue"] { 
    print(value) // prints 2 
} 

Он также не по назначению, когда вы делаете вещи, которые не могут работать.

if let value: Int = dict["dict"] { 
    print(value) // is not executed 
} 

if let value: Int = dict["dict"]["nestedDict"]["nestedValue"] { 
    print(value) // is not executed 
} 

И вы даже можете установить значение в вложенных словарях, которые не были созданы еще !:

dict["dict"]["nestedDict2"]["nestedValue"] = 3 


if let value: Int = dict["dict"]["nestedDict2"]["nestedValue"] { 
    print(value) // prints 3 
} 
0

Очень мало информации .. и вы имеете в виду бесконечные вложенные словари? Я не думаю, что так ..

func returnDict() -> Dictionary<String, AnyObject> { 
     return ["Got You" : returnDict()] 
    } 


var x : Dictionary<String, AnyObject> = ["GotYou" : returnDict()] 

Просто говоря, ничего лучше не может случиться с этим, кроме аварии

это случай бесконечной рекурсии. Когда у вас есть бесконечные словари, это не значит, что он будет работать вечно. Это означает, что он будет работать до тех пор, пока на вашем устройстве не останется память. Вызов функции returnDict, вызывает returnDict, который снова вызывает returnDict и т. Д.

Рекурсия в основном добавляет метод в стек уже существующего стека методов в памяти. Это может произойти до тех пор, пока стек не переполнится. Следовательно, Stackoverflow

let node1: Dictionary<String, AnyObject!> = ["foo" : nil] 
var node2 = ["bar" : node1] 

площадка одобряет его

enter image description here

+0

Мне нужны были бесконечные гнезда. Вот почему это сложно. – Daniel

+0

зачем вам бесконечные гнезда? И как это вам поможет? –

+0

Причина Я знаю только во время выполнения, насколько глубока она должна быть. – Daniel

0

Причина заключается в том, что, как в значения Objective-C в Dictionary типа должно быть не обязательным.

Это не очень полезно в любом случае, поскольку в Swift присвоение ключа nil ключу удаляет ключ.

var node1: Dictionary<String, AnyObject> = ["foo" : "Hello"] 
var node2: Dictionary<String, AnyObject> = ["bar" : node1] 
1

Я работал с firebase, и мне нужно, чтобы достичь структуры, подобной этой:

["llave3": ["hola": "", "dos": ""], "llave1": ["hola": "", "dos": ""],  "llave2": ["hola": "", "dos": ""]] 

Это вложенный словарь или словарь словарей. Я достигла этого, просто сделав это:

var array = ["llave1", "llave2","llave3"] 
var dictOfDictionarys = [String : [String : String]]() 

for items in array { 
     dictOfDictionarys[items] = ["hola":"","dos":""] 
} 
Смежные вопросы