Перебор словаря в Swift

222

Я немного смущен ответом, который XCode дает мне на этот эксперимент в Руководстве по языку программирования 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

Я понимаю, что, поскольку словарь пересекается, наибольшее число устанавливается для переменной largest. Тем не менее, я не понимаю, почему Xcode говорит, что largestон устанавливается 5, или 1, или 3 раза, в зависимости от каждого теста.

Просматривая код, я вижу, что он должен быть установлен 6 раз только в «Prime» (2, 3, 5, 7, 11, 13). Затем следует пропустить любые числа в «Фибоначчи», так как они все меньше, чем наибольшее, которое в настоящее время установлено в 13 от «Prime». Затем он должен быть установлен в 16, и, наконец, 25 в «Квадрат», в результате чего в общей сложности 8 раз.

Я что-то упускаю совершенно очевидное?

Ник Корн
источник

Ответы:

356

Словари в Swift (и других языках) не упорядочены. Когда вы просматриваете словарь, нет гарантии, что порядок будет соответствовать порядку инициализации. В этом примере Swift обрабатывает клавишу «Квадрат» раньше других. Вы можете увидеть это, добавив оператор print в цикл. 25 является 5-м элементом Квадрата, поэтому самый большой будет установлен 5 раз для 5 элементов в Квадрате, а затем останется равным 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

Это печатает:

kind: Square
kind: Prime
kind: Fibonacci
тир
источник
1
Спасибо вам большое! Я был озадачен на некоторое время. Я продолжал добавлять и удалять номера для каждого ключа в надежде разобрать его, но ничего не получалось. Ваше объяснение ясно очень ценится!
Ник Корн
15
let dict : [String : Any] = ["FirstName" : "Maninder" , "LastName" : "Singh" , "Address" : "Chandigarh"]
dict.forEach { print($0) }

Результат будет

("FirstName", "Maninder") ("LastName", "Singh") ("Адрес", "Чандигарх")

Maninderjit Singh
источник
Не могли бы вы сказать мне, является ли этот пример более эффективным в цикле данных 1000? Потому что у меня такой большой JSON, так что в конце мне понадобится 1 ГБ обработки. Более новые устройства не будут аварийно завершаться, но в моем iphone 5s 16GB происходит сбой на половине этого.
Даниэль Арантес Ловерде
Это кажется немного вводящим в заблуждение, учитывая, что первоначальный вопрос о том, поддерживают ли словари свой порядок, тогда вы публикуете пример, где они поддерживают свой порядок, когда они этого не делают.
Деклан МакКенна
12

Это пользовательская функция для перебора словаря:

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

Вот альтернатива для этого эксперимента (Swift 3.0). Это говорит вам, какой именно номер был самым большим.

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
источник
8

Если вы хотите перебрать все значения:

dict.values.forEach { value in
    // print(value)
}
norbDEV
источник
Я так ненавижу этот факт, что это правильно. В глупой Йоде говорите с создателем Свифта каждый должен говорить! 🤮
Себастьян
4

Массивы - это упорядоченные коллекции, а словари и наборы - неупорядоченные коллекции. Таким образом, вы не можете предсказать порядок итераций в словаре или наборе.

Прочтите эту статью, чтобы узнать больше о типах коллекций: язык программирования Swift

Рачит Рават
источник
1

Вы также можете использовать values.makeIterator()для перебора значений dict, например так:

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

Вы также можете выполнить итерацию следующим образом в более быстром стиле:

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

* sbItemsявляется диктатом типа[String : NSManagedObject]

Йонатан Горячник
источник