Сортировать словарь по значению с элементом связывания не следует менять их порядок

У меня есть словарь типа [String: Int] и его значение

let dic = [“a”:4, “b”:3, “c”:3]

Я хочу отсортировать словарь по значению и используя метод

dic  = dic.sorted(by: { $0.value < $1.value })

Результат

dic = [“c”:3, “b”:3, “a”:4]

Это сортировка по словарю, но я хочу, чтобы значения, которые были одинаковыми, не сортировались и не меняли порядок, например, я хочу получить такой результат

dic = [“b”:3, “c”:3, “a”:4]

2 ответа

Решение

Основная проблема здесь в том, что словарь - это неупорядоченная коллекция, поэтому пытаться сортировать его - не лучшая вещь.

Если вы хотите сохранить значения для вашей игры (например, для таблицы лидеров), вы можете использовать кортежи.

typealias Score = (username: String, score: Int)

Затем use может создать массив этих кортежей и отсортировать их по своему усмотрению.

var scores = [Score]()

// fill the scores
scores.append(("a", 4))
scores.append(("b", 3))
scores.append(("c", 3))

scores.sort {
    return $0.score < $1.score || ($0.score == $1.score && $0.username.localizedCaseInsensitiveCompare($1.username) == .orderedAscending)
}

Словарь неупорядочен. Это означает, что независимо от того, какой порядок вы видите в коде, KVP не гарантируется. sort call только говорит, что сортирует по значениям, поэтому ключи могут быть в любом порядке, который они хотят.

Также обратите внимание, что Свифт sorted(by:) не является стабильным Это означает, что вещи, которые считаются равными, не гарантируют сохранение своего порядка.

Следовательно, вы ничего не можете с этим поделать, если будете настаивать на использовании встроенных алгоритмов Swift. Вы можете написать сортировку вставкой (алгоритм стабильной сортировки) и использовать ее.

Другое решение - упорядочить KVP по значениям, а затем по ключам:

let newDict = dict.sorted(by: { $0.value == $1.value ? $0.key < $1.key : $0.value < $1.value })

Очевидно, это будет работать только в том случае, если имена ваших игроков изначально упорядочены лексикографически.

Или создайте Player структурировать и использовать массив Players:

struct Player {
    let name: String
    var score: Int
}
Другие вопросы по тегам