Itération à travers un dictionnaire dans Swift


221

Je suis un peu confus sur la réponse que Xcode me donne à cette expérience dans le Guide du langage de programmation 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

Je comprends que le dictionnaire est transversed, le plus grand nombre est d' être mis à la variable, largest. Cependant, je ne comprends pas pourquoi Xcode dit que cela largestest réglé 5 fois, ou 1 fois, ou 3 fois, selon chaque test.

Lorsque je regarde le code, je vois qu'il doit être réglé 6 fois dans "Prime" seul (2, 3, 5, 7, 11, 13). Ensuite, il devrait ignorer tous les nombres dans "Fibonacci" car ceux-ci sont tous inférieurs au plus grand, qui est actuellement réglé à 13 depuis "Prime". Ensuite, il doit être réglé sur 16, et enfin 25 sur "Square", ce qui donne un total de 8 fois.

Suis-je en train de manquer quelque chose de complètement évident?

Réponses:


355

Les dictionnaires en Swift (et dans d'autres langues) ne sont pas commandés. Lorsque vous parcourez le dictionnaire, il n'y a aucune garantie que l'ordre correspondra à l'ordre d'initialisation. Dans cet exemple, Swift traite la touche "Carré" avant les autres. Vous pouvez le voir en ajoutant une instruction print à la boucle. 25 est le 5ème élément de Square, donc le plus grand serait réglé 5 fois pour les 5 éléments de Square, puis resterait à 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

Cela imprime:

kind: Square
kind: Prime
kind: Fibonacci

1
Merci beaucoup! J'ai été perplexe pendant un petit moment. J'ai continué à ajouter et à supprimer des numéros pour chaque clé dans l'espoir de la disséquer, mais je n'allais nulle part. Votre explication est claire très appréciée!
Nick Kohrn

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

Le résultat serait

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


Pourriez-vous me dire si cet exemple est plus efficace dans une boucle de 1000 données? Parce que j'ai un JSON aussi gros, donc il me faut un traitement de 1 Go à la fin. Les nouveaux appareils ne plantent pas, mais dans mon iphone 5s, 16 Go tombent en panne sur la moitié.
Daniel Arantes Loverde

Cela semble un peu trompeur étant donné que la question initiale est de savoir si les dictionnaires maintiennent leur ordre, alors vous publiez un exemple où ils maintiennent leur ordre quand ils ne le font pas.
Declan McKenna du

12

Il s'agit d'une fonction définie par l'utilisateur pour parcourir un dictionnaire:

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

Voici une alternative pour cette expérience (Swift 3.0). Cela vous indique exactement quel type de numéro était le plus grand.

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 vous souhaitez parcourir toutes les valeurs:

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

Je déteste tellement le fait que c'est correct. En stupide Joda parler au créateur de rapide tout le monde doit parler! 🤮
Sebastian


1

Vous pouvez également utiliser values.makeIterator()pour parcourir les valeurs de dict, comme ceci:

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

Vous pouvez également faire l'itération comme ceci, dans un style plus rapide:

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

* sbItemsest un dict de type[String : NSManagedObject]

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.