Scorrere un dizionario in Swift


221

Sono un po 'confuso sulla risposta che Xcode mi sta dando a questo esperimento nella Guida al linguaggio di programmazione 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

Capisco che il dizionario è transversed, il maggior numero viene impostata alla variabile, largest. Tuttavia, sono confuso sul perché Xcode lo stia dicendolargest viene impostato 5 volte, oppure 1 volta o 3 volte, a seconda di ciascun test.

Quando guardo il codice, vedo che dovrebbe essere impostato 6 volte in "Prime" da solo (2, 3, 5, 7, 11, 13). Quindi dovrebbe saltare qualsiasi numero in "Fibonacci" poiché quelli sono tutti meno del più grande, che è attualmente impostato su 13 da "Prime". Quindi, dovrebbe essere impostato su 16 e infine su 25 in "Square", per un totale di 8 volte.

Mi sto perdendo qualcosa di completamente ovvio?

Risposte:


355

I dizionari in Swift (e in altre lingue) non sono ordinati. Quando si scorre il dizionario, non esiste alcuna garanzia che l'ordine corrisponderà all'ordine di inizializzazione. In questo esempio, Swift elabora il tasto "Quadrato" prima degli altri. Puoi vederlo aggiungendo un'istruzione print al loop. 25 è il 5 ° elemento di Square, quindi il più grande verrebbe impostato 5 volte per i 5 elementi in Square e quindi rimarrebbe a 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

Questo stampa:

kind: Square
kind: Prime
kind: Fibonacci

1
Grazie mille! Sono rimasto per un attimo perplesso. Continuavo ad aggiungere e rimuovere numeri per ogni chiave nella speranza di analizzarla, ma non andavo da nessuna parte. La tua spiegazione è chiara e molto apprezzata!
Nick Kohrn,

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

Il risultato sarebbe

("FirstName", "Maninder") ("LastName", "Singh") ("Indirizzo", "Chandigarh")


Potresti dirmi se questo esempio è più efficiente in un ciclo di 1.000 dati? Perché ho un JSON così grande, quindi alla fine mi ci vuole un'elaborazione da 1 GB. I dispositivi più recenti non si arrestano in modo anomalo, ma nel mio iPhone 5s 16 GB si bloccano su metà.
Daniel Arantes Loverde,

Questo sembra un po 'fuorviante dato che la domanda originale è se i dizionari mantengono il loro ordine, quindi pubblichi un esempio in cui mantengono il loro ordine quando non lo fanno.
Declan McKenna,

12

Questa è una funzione definita dall'utente per scorrere attraverso un dizionario:

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

Ecco un'alternativa a quell'esperimento (Swift 3.0). Questo ti dice esattamente quale tipo di numero era il più 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

Se vuoi iterare su tutti i valori:

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

Odio il fatto così tanto, che questo è corretto. In stupido Joda parla con il creatore di rapido tutti devono parlare! 🤮
Sebastian,


1

Puoi anche utilizzare values.makeIterator()per scorrere i valori di dict, in questo modo:

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

Puoi anche eseguire l'iterazione in questo modo, in uno stile più veloce:

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

* sbItemsè dettato dal tipo[String : NSManagedObject]

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.