Iterando através de um dicionário no Swift

221

Estou um pouco confuso com a resposta que o Xcode está me dando para esse experimento no Swift Programming Language Guide:

// 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

Entendo que, como o dicionário está sendo cruzado, o maior número está sendo definido para a variável largest. No entanto, estou confuso sobre o motivo pelo qual o Xcode está dizendo que largestestá sendo definido 5 vezes, ou 1 vez ou 3 vezes, dependendo de cada teste.

Ao examinar o código, vejo que ele deve ser definido 6 vezes apenas em "Prime" (2, 3, 5, 7, 11, 13). Em seguida, deve pular todos os números em "Fibonacci", pois esses são todos menores que o maior, atualmente definido como 13 em "Prime". Em seguida, deve ser definido como 16 e, finalmente, 25 em "Quadrado", resultando em um total de 8 vezes.

Estou perdendo algo totalmente óbvio?

Nick Kohrn
fonte

Respostas:

355

Os dicionários em Swift (e em outros idiomas) não são solicitados. Quando você percorre o dicionário, não há garantia de que o pedido corresponda ao pedido de inicialização. Neste exemplo, Swift processa a tecla "Square" antes das outras. Você pode ver isso adicionando uma declaração de impressão ao loop. 25 é o quinto elemento do quadrado, então o maior seria definido 5 vezes para os 5 elementos no quadrado e depois permaneceria em 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

Isso imprime:

kind: Square
kind: Prime
kind: Fibonacci
Traço
fonte
1
Muito obrigado! Fiquei perplexo por um tempo. Continuei adicionando e removendo números para cada tecla na esperança de dissecá-lo, mas não estava chegando a lugar nenhum. Sua explicação é clara, muito apreciada!
Nick Kohrn
15
let dict : [String : Any] = ["FirstName" : "Maninder" , "LastName" : "Singh" , "Address" : "Chandigarh"]
dict.forEach { print($0) }

O resultado seria

("Nome", "Maninder") ("Sobrenome", "Singh") ("Endereço", "Chandigarh")

Maninderjit Singh
fonte
Você poderia me dizer se este exemplo é mais eficiente em um loop de 1.000 dados? Porque eu tenho um JSON tão grande, então levo um processamento de 1 GB no final. Os dispositivos mais recentes não travam, mas no meu iphone 5s 16GB trava em metade disso.
Daniel Arantes Loverde
Isso parece um pouco enganador, considerando que a pergunta original é se os dicionários mantêm sua ordem e, em seguida, você publica um exemplo em que eles mantêm sua ordem quando não o fazem.
Declan McKenna
12

Esta é uma função definida pelo usuário para iterar através de um dicionário:

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
fonte
11

Aqui está uma alternativa para esse experimento (Swift 3.0). Isso informa exatamente qual tipo de número foi o maior.

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
fonte
8

Se você deseja iterar sobre todos os valores:

dict.values.forEach { value in
    // print(value)
}
norbDEV
fonte
Eu odeio tanto o fato, que isso está correto. Em Joda estúpido, fale com o criador do rápido, todos devem falar! 🤮
Sebastian
4

Matrizes são coleções ordenadas, mas dicionários e conjuntos são coleções não ordenadas. Portanto, você não pode prever a ordem da iteração em um dicionário ou conjunto.

Leia este artigo para saber mais sobre os Tipos de coleção: Linguagem de programação rápida

Rachit Rawat
fonte
1

Você também pode usar values.makeIterator()para iterar sobre valores de dict, assim:

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

Você também pode fazer a iteração dessa maneira, em um estilo mais rápido:

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

* sbItemsé ditado do tipo[String : NSManagedObject]

Yonathan Goriachnick
fonte