Iterando a través de un diccionario en Swift


221

Estoy un poco confundido con la respuesta que Xcode me está dando a este experimento en la Guía del lenguaje de programación Swift:

// Use a for-in to iterate through a dictionary (experiment)

let interestingNumbers = [
    "Prime": [2, 3, 5, 7, 11, 13],
    "Fibonacci": [1, 1, 2, 3, 5, 8],
    "Square": [1, 4, 9, 16, 25]
]
var largest = 0
for (kind, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
        }
    }
}
largest

Yo entiendo que a medida que el diccionario está siendo atravesada, el número más grande se está creando a la variable, largest. Sin embargo, estoy confundido sobre por qué Xcode dice que largestse está configurando 5 veces, o 1 vez, o 3 veces, dependiendo de cada prueba.

Cuando reviso el código, veo que debe configurarse 6 veces solo en "Prime" (2, 3, 5, 7, 11, 13). Luego, debe omitir cualquier número en "Fibonacci", ya que todos son menores que el más grande, que actualmente está establecido en 13 desde "Prime". Luego, debe establecerse en 16, y finalmente en 25 en "Cuadrado", dando un total de 8 veces.

¿Me estoy perdiendo algo completamente obvio?

Respuestas:


355

Los diccionarios en Swift (y otros idiomas) no están ordenados. Cuando itera por el diccionario, no hay garantía de que el orden coincida con el orden de inicialización. En este ejemplo, Swift procesa la tecla "Cuadrado" antes que las demás. Puede ver esto agregando una declaración de impresión al bucle. 25 es el quinto elemento de Square, por lo que el más grande se establecería 5 veces para los 5 elementos en Square y luego se mantendría en 25.

let interestingNumbers = [
    "Prime": [2, 3, 5, 7, 11, 13],
    "Fibonacci": [1, 1, 2, 3, 5, 8],
    "Square": [1, 4, 9, 16, 25]
]
var largest = 0
for (kind, numbers) in interestingNumbers {
    println("kind: \(kind)")
    for number in numbers {
        if number > largest {
            largest = number
        }
    }
}
largest

Esto imprime:

kind: Square
kind: Prime
kind: Fibonacci

1
Muchas gracias! Estuve perplejo por un rato. Seguí agregando y eliminando números para cada tecla con la esperanza de diseccionarlo, pero no estaba llegando a ninguna parte. Su explicación es clara muy apreciada!
Nick Kohrn

15
let dict : [String : Any] = ["FirstName" : "Maninder" , "LastName" : "Singh" , "Address" : "Chandigarh"]
dict.forEach { print($0) }

El resultado sería

("Nombre", "Maninder") ("Apellido", "Singh") ("Dirección", "Chandigarh")


¿Podría decirme si este ejemplo es más eficiente en un bucle de 1000 datos? Porque tengo un JSON tan grande, así que me lleva un procesamiento de 1GB al final. Los dispositivos más nuevos no se bloquean, pero en mi iPhone 5s se bloquean 16 GB en la mitad de eso.
Daniel Arantes Loverde

Esto parece un poco engañoso dado que la pregunta original es sobre si los diccionarios mantienen su orden y luego publica un ejemplo en el que mantienen su orden cuando no lo hacen.
Declan McKenna

12

Esta es una función definida por el usuario para iterar a través de un diccionario:

func findDic(dict: [String: String]){
    for (key, value) in dict{
    print("\(key) : \(value)")
  }
}

findDic(dict: ["Animal":"Lion", "Bird":"Sparrow"])
//prints Animal : Lion 
         Bird : Sparrow

11

Aquí hay una alternativa para ese experimento (Swift 3.0). Esto le dice exactamente qué tipo de número fue el más grande.

let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]

var largest = 0
var whichKind: String? = nil

for (kind, numbers) in interestingNumbers {
    for number in numbers {
    if number > largest {
        whichKind = kind
        largest = number
    }
  }
}

print(whichKind)
print(largest)

OUTPUT:
Optional("Square")
25

8

Si desea iterar sobre todos los valores:

dict.values.forEach { value in
    // print(value)
}

Odio tanto el hecho, que esto es correcto. ¡En la estúpida Joda, habla con el creador de Swift, todos deben hablar! 🤮
Sebastian


1

También puede usar values.makeIterator()para iterar sobre valores dict, como este:

for sb in sbItems.values.makeIterator(){
    // do something with your sb item..
    print(sb)
}

También puede hacer la iteración de esta manera, en un estilo más rápido:

sbItems.values.makeIterator().forEach{
    // $0 is your dict value..
    print($0) 
}

* sbItemses dict de tipo[String : NSManagedObject]

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.