arrays - recorrer - swift: modificando arreglos dentro de diccionarios
uso de diccionarios en swift 3 (4)
¿Cómo puedo agregar elementos fácilmente a una matriz dentro de un diccionario? Siempre se está quejando con could not find member ''append''
o could not find an overload for ''+=''
var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]
// all of these fail
dict["key"] += 4
dict["key"].append(4) // xcode suggests dict["key"].?.append(4) which also fails
dict["key"]!.append(4)
dict["key"]?.append(4)
// however, I can do this:
var arr = dict["key"]!
arr.append(4) // this alone doesn''t affect dict because it''s a value type (and was copied)
dict["key"] = arr
si solo asigno el arreglo a una var, lo modifico y luego lo reasigno al dict, ¿no estaré copiando todo? eso no sería eficiente ni elegante.
Como una solución simple, puede usar un NSMutableArray:
import Foundation
var dict = Dictionary<String, NSMutableArray>()
dict["key"] = [1, 2, 3] as NSMutableArray
dict["key"]!.addObject(4)
Estoy utilizando efectivamente una solución tan simple en mi proyecto:
Esto es lo que le estaba diciendo a Nate Cook, en los comentarios por su respuesta de calidad. Esto es lo que considero "agregar [fácilmente] elementos a una matriz dentro de un diccionario":
dict["key"] = dict["key"]! + 4
dict["key"] = dict["key"] ? dict["key"]! + 4 : [4]
Por ahora, necesitamos definir el operador + nosotros mismos.
@infix func +<T>(array: T[], element: T) -> T[] {
var copy = array
copy += element
return copy
}
Creo que esta versión elimina demasiada seguridad; tal vez definirlo con un operador compuesto?
@infix func +<T>(array: T[]?, element: T) -> T[] {
return array ? array! + element : [element]
}
dict["key"] = dict["key"] + 4
Finalmente, este es el más limpio que puedo obtener, pero estoy confundido acerca de cómo funcionan los valores / referencias de matriz en este ejemplo.
@assignment func +=<T>(inout array: T[]?, element: T) {
array = array + element
}
dict["key"] += 5
Swift beta 5 ha agregado esta funcionalidad, y has identificado el nuevo método en un par de tus intentos. ¡Los operadores que desenvuelven !
y ?
ahora pase el valor a cualquiera de los operadores o llamadas a métodos. Es decir, puede agregar a esa matriz de cualquiera de estas maneras:
dict["key"]! += [4]
dict["key"]!.append(4)
dict["key"]?.append(4)
Como siempre, tenga cuidado con el operador que usa: forzar el desenvolvimiento de un valor que no está en su diccionario le dará un error de tiempo de ejecución:
dict["no-key"]! += [5] // CRASH!
Mientras que usar el encadenamiento opcional fallará silenciosamente:
dict["no-key"]?.append(5) // Did it work? Swift won''t tell you...
Idealmente, ¿podría usar el nuevo operador coalescente nulo ??
para abordar este segundo caso, pero en este momento eso no está funcionando.
Respuesta de pre-Swift beta 5:
Es un capricho de Swift que no es posible hacer lo que estás tratando de hacer. El problema es que el valor de cualquier variable opcional es, de hecho, una constante, incluso cuando se desenvuelve a la fuerza. Si solo definimos una matriz opcional, esto es lo que podemos y no podemos hacer:
var arr: Array<Int>? = [1, 2, 3]
arr[0] = 5
// doesn''t work: you can''t subscript an optional variable
arr![0] = 5
// doesn''t work: constant arrays don''t allow changing contents
arr += 4
// doesn''t work: you can''t append to an optional variable
arr! += 4
arr!.append(4)
// these don''t work: constant arrays can''t have their length changed
La razón por la que tiene problemas con el diccionario es que al suscribir un diccionario devuelve un valor opcional, ya que no hay garantía de que el diccionario tenga esa clave. Por lo tanto, una matriz en un diccionario tiene el mismo comportamiento que la matriz opcional anterior:
var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]
dict["key"][0] = 5 // doesn''t work
dict["key"]![0] = 5 // doesn''t work
dict["key"] += 4 // uh uh
dict["key"]! += 4 // still no
dict["key"]!.append(4) // nope
Si necesita cambiar algo de una matriz en el diccionario, deberá obtener una copia de la matriz, cambiarla y reasignarla así:
if var arr = dict["key"] {
arr.append(4)
dict["key"] = arr
}
ETA: la misma técnica funciona en Swift beta 3, aunque las matrices constantes ya no permiten cambios en los contenidos.
Use ''for in'' para obtener valores del conjunto interno del diccionario. Aquí hay un ejemplo para ayudarte
var a = ["x":["a","b","c"], "y":["d"]]
for b in a {
print(b)
}
Salida:
("x", ["d"])
("y", ["a", "b", "c"])