Beim Zusammenstellen einer Datennutzlast, die an GRMustache.Swift übergeben wird, um Schnurrbartvorlagen zu rendern, befinde ich mich in einem Szenario, in dem ich Daten an ein zuvor im Wörterbuch definiertes Array anhängen muss.
Meine Datenstruktur beginnt mit:
var data: [String: Any] = [
"key1": "example value 1",
"key2": "example value 2",
"items": [
// I need to append here later
]
]
Das items
-Schlüsselpaar ist eine Sammlung, die ich später in einer Schleife anfügen muss.
Um das data["items"]
-Array hinzuzufügen, versuche ich Folgendes:
for index in 1...3 {
let item: [String: Any] = [
"key": "new value"
]
data["items"].append(item)
}
Dieser Fehler hat als Wert des Typs Any?
kein Member append
und der binäre Operator +=
kann nicht auf Operanden vom Typ Any?
und [String : Any]
angewendet werden.
Das macht Sinn, da ich den Wert anhängen muss; Ich kann das Array jedoch nicht mutieren.
Casting in Array, ob das Erzwingen des Downcasts den Fehler verursacht:
(data["items"] as! Array).append(item)
'Irgendein?' kann nicht in 'Array <_>' konvertiert werden; Wolltest du "als!" verwenden? niedergeschlagen zwingen
Mutationsmitglied kann nicht für unveränderliche Werte des Typs 'Array <_>' verwendet werden
Scheint, dass meine Besetzung falsch ist; oder, vielleicht gehe ich falsch vor.
Gibt es eine Empfehlung, wie Sie data["items"]
im Laufe der Zeit iterativ füllen?
Der Typ von data[Items]
ist nicht Array
sondern tatsächlich Array<[String: Any]>
.
Sie könnten dies wahrscheinlich in weniger Schritten zusammenpressen, aber ich bevorzuge die Klarheit mehrerer Schritte:
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
}
Wenn Sie lieber Kürze als Klarheit bevorzugen, können Sie diesen Vorgang in einer einzigen Zeile ausführen. Verwenden Sie dazu den nil
-Koaleszenzoperator und den +
-Operator für RangeReplaceableCollection
(dem Array
entspricht), wobei letzterer für den Schritt "Anhängen" verwendet wird (Erstellen einer neuen Sammlung, die die vorhandene ersetzt, wenn der Wert von data["items"]
ersetzt wird).
// 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"] */
subscript
mit Dictionary
gibt immer eine optional(?)
-Instanz zurück, da möglicherweise key
nicht in Dictionary
vorhanden ist. Jetzt haben Sie Ihr Wörterbuch als [String:Any]
bezeichnet, wobei der Typ von key
String
und value
Any
ist.
Wenn Sie jetzt data["item"]
schreiben, werden Sie Any?
zurückgegeben, bei dem es sich nicht um Array handelt. Daher können Sie append
nicht aufrufen. Es wird ein unveränderlicher Wert zurückgegeben, sodass Sie ihn nicht direkt mutieren können.
Sie müssen es also in Array of Dictionary umwandeln und in Instanz speichern und diese Instanz anfügen. Ersetzen Sie dann dieses Objekt in Ihrem Wörterbuch, indem Sie es neu zuweisen.
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
}
Jetzt ist es viel einfacher, wenn Sie Dictionary
wie [String: [[String:Any]]]
für zB haben.
var data: [String: [[String:Any]]] = [
"items": []
]
for index in 1...3 {
let item: [String: Any] = [
"key": "new value"
]
data["items"]?.append(item)
}
Ich bin mir nicht ganz sicher, ob dies für den Wörterbuchtyp [String: Any] funktioniert, empfehle jedoch dringend, eine Struktur zu erstellen, anstatt "Any" für Ihr Wörterbuch zu verwenden. Es hilft, die Dinge viel reibungsloser laufen zu lassen.
Andererseits wollte ich erwähnen, dass Sie etwas ausprobieren können wie:
yourDictionary["Key", default: []].append(item)
Dadurch wird ein Array für diesen "Schlüssel" initialisiert, der im Wörterbuch verwendet wird, wenn noch kein Array initialisiert wurde. Ohne dies müssten Sie das Array selbst überprüfen und initialisieren, was letztendlich zu einem sich wiederholenden Code führt.
Hoffe das hilft.
Gib dir eine Array
von items:[String]
Er kann dies auch dem Json hinzufügen
var items = ["string1", "Info 2","Text 4"]
data["items"] = items