2017-01-07 8 views
9

データペイロードを組み立ててGRMustache.swiftに渡すと、ひげ模様テンプレートがレンダリングされます。以前に辞書で定義した配列にデータを追加する必要があります。[String:Any]ディクショナリ構造体に配列に追加する

私のデータ構造としてオフ開始します。

var data: [String: Any] = [ 
    "key1": "example value 1", 
    "key2": "example value 2", 
    "items": [ 
     // I need to append here later 
    ] 
] 

items鍵のペアは、私はループ内で、後で追加する必要がありますコレクションです。タイプAny?の値がまったくメンバーappendを持っていない、と二項演算子+=はタイプのオペランドに適用することができないよう、

for index in 1...3 { 
    let item: [String: Any] = [ 
     "key": "new value" 
    ] 

    data["items"].append(item) 
} 

このエラーAny?data["items"]アレイに追加するには

、私のような何かをしようとしていますおよび[String : Any]

追加する値をキャストする必要があるため、これは意味があります。しかし、配列を突然変異させることはできません。 ;私のキャストは間違っているよう

(data["items"] as! Array).append(item) 

'Any?' is not convertible to 'Array<_>'; did you mean to use 'as!' to force downcast?

Cannot use mutating member on immutable value of type 'Array<_>'

は思える:意気消沈を強制的にエラーを与えるかどうか、配列にキャスト

または、おそらく私は間違った方法でこれについて行くつもりです。

時間の経過とともに反復的にdata["items"]を記入する方法に関する推奨事項はありますか?

答えて

6

data[Items]のタイプはArrayではなく、実際にはArray<[String: Any]>です。

あなたはおそらく少ないステップにこれを絞ることができますが、私は複数のステップの明確さを好む:それは可能keyDictionaryに存在していない場合があるためDictionary

var data: [String: Any] = [ 
    "key1": "example value 1", 
    "key2": "example value 2", 
    "items": [] 
] 

for index in 1...3 { 

    let item: [String: Any] = [ 
     "key": "new value" 
    ] 

    // get existing items, or create new array if doesn't exist 
    var existingItems = data["items"] as? [[String: Any]] ?? [[String: Any]]() 

    // append the item 
    existingItems.append(item) 

    // replace back into `data` 
    data["items"] = existingItems 
} 
3

subscriptは常にoptional(?)インスタンスを返します。あなたの辞書を[String:Any]とし、keyのタイプがStringvalueAnyであると宣言しました。あなたがdata["item"]を書くとき

今、それはあなたがappendと呼ばれることができない、あなたはそれを直接変異させることができないので、それは不変の値を返しますので、配列ではないAny?を返します。

辞書に辞書をキャストしてインスタンスに保存し、そのインスタンスを辞書に追加し直す必要があります。

for index in 1...3 { 
    let item: [String: Any] = [ 
     "key": "new value" 
    ] 

    var array = data["items"] as? [[String:Any]] ?? [[String:Any]]() 
    array.append(item) 
    data["items"] = array 
} 

は今のものは、あなたが例えばため[String: [[String:Any]]]のようなDictionaryを持っている場合、非常に簡単になっています。あなたが明瞭上簡潔さを好む場合は、nil合体オペレータとthe + operator for RangeReplaceableCollection(へArray適合)を利用して、一列にこの操作を行うことができる

var data: [String: [[String:Any]]] = [ 
    "items": [] 
] 

for index in 1...3 { 
    let item: [String: Any] = [ 
     "key": "new value" 
    ] 
    data["items"]?.append(item) 
} 
+0

@JasonSturgesこれを追加することができ、私は問題とどこができた何をちょうど示しているがあります与えます辞書の中にあった配列を直接追加します。 –

+1

'[String:[[String:Any]]]型の明快さと優雅さを本当に感謝します。 –

+0

上記の 'data [" items "]!append(item)'ではなく、 'data [" items "]?append(item)'を使うことができます。後者は '' items ''キーの値がなくても(この例にあるとわかっていても)、ランタイムクラッシュを引き起こしますが、前者は単純に未使用の' nil'を返します。私たちが存在する "アイテム"の鍵を知っていても、特に余分なコストがかからない場合には、安全なアプローチを選ぶべきだと思う。初心者のSO読者のために、この特定の事例/例では '!'が安全であることを認識しない悪い '!'練習を強化するリスクは常にありますが、それ以外の場合は一般的ではありません。 – dfri

3

、「追加」ステップ(に使用後者実際にはdata["items"]の値を置き換えるときに既存のコレクションを置き換える新しいコレクションを作成します)。

// example setup 
var data: [String: Any] = [ 
    "key1": "example value 1", 
    "key2": "example value 2", 
    "items": [] 
] 

// copy-mutate-replace the "items" array inline, adding a new dictionary 
data["items"] = (data["items"] as? [[String: Any]] ?? []) + [["key": "new value"]] 

print(data) 
/* ["key2": "example value 2", 
    "items": [["key": "new value"]], 
    "key1": "example value 1"]  */ 

// add another dictionary to the "items" array 
data["items"] = (data["items"] as? [[String: Any]] ?? []) + [["key": "new value"]] 

print(data) 
/* ["key2": "example value 2", 
"items": [["key": "new value"], ["key": "new value"]], 
"key1": "example value 1"]  */ 
0

あなたはitems:[String]

Array彼はまた、JSONに私が知っている

var items = ["string1", "Info 2","Text 4"] 

data["items"] = items 
関連する問題