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?

Nick Kohrn
la source

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
Tiret
la source
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")

Maninderjit Singh
la source
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
Rawand Saeed
la source
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
jabbyApps
la source
8

Si vous souhaitez parcourir toutes les valeurs:

dict.values.forEach { value in
    // print(value)
}
norbDEV
la source
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
4

Les tableaux sont des collections ordonnées mais les dictionnaires et les ensembles sont des collections non ordonnées. Ainsi, vous ne pouvez pas prédire l'ordre d'itération dans un dictionnaire ou un ensemble.

Lisez cet article pour en savoir plus sur les types de collection: langage de programmation Swift

Rachit Rawat
la source
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]

Yonathan Goriachnick
la source