Вы можете немного упростить это, сгруппировав команды с одинаковыми баллами в словаре. Затем отсортируйте словарь (по убыванию оценки), перечислите его (чтобы получить смещения) и составьте список рейтинга:
let dict:[String:Int] = ["team1":79, "team2":5, "team3":18, "team4":5, "team5": 82, "team6": 1]
let ranking = Dictionary(grouping: dict, by: { $0.value })
.sorted(by: { $0.key > $1.key })
.enumerated()
.flatMap { (offset, elem) in
elem.value.map { (team: $0.key, rank: offset + 1 )}
}
print(ranking)
// [(team: "team5", rank: 1), (team: "team1", rank: 2),
// (team: "team3", rank: 3), (team: "team2", rank: 4),
// (team: "team4", rank: 4), (team: "team6", rank: 5)]]
Подробное объяснение:
Dictionary(grouping: dict, by: { $0.value })
создает словарь, ключами которого являются результаты команд, а значениями являются массивы команд с таким счетом.
.sorted(by: { $0.key > $1.key })
сортирует словарь по убыванию ключей, в результате получается массив кортежей:
[(key: 82, value: [(key: "team5", value: 82)]),
(key: 79, value: [(key: "team1", value: 79)]),
(key: 18, value: [(key: "team3", value: 18)]),
(key: 5, value: [(key: "team2", value: 5), (key: "team4", value: 5)]),
(key: 1, value: [(key: "team6", value: 1)])]
Тогда
.enumerated()
создает ленивую последовательность пар (смещение, элемент) из этого массива:
(offset: 0, element: (key: 82, value: [(key: "team5", value: 82)])),
(offset: 1, element: (key: 79, value: [(key: "team1", value: 79)])),
(offset: 2, element: (key: 18, value: [(key: "team3", value: 18)])),
(offset: 3, element: (key: 5, value: [(key: "team2", value: 5), (key: "team4", value: 5)])),
(offset: 4, element: (key: 1, value: [(key: "team6", value: 1)]))
Наконец, flatMap
вызывает замыкание для каждой пары (смещение, элемент) и объединяет результат. Внутри закрытия,
elem.value.map { (team: $0.key, rank: offset + 1 )}
отображает пару (смещение, элемент) и массив (команда, ранг) кортежей. Например,
(offset: 3, element: (key: 5, value: [(key: "team2", value: 5), (key: "team4", value: 5)]))
отображается на
[(team: "team2", rank: 4), (team: "team4", rank: 4)]
flatMap()
объединяет эти массивы, давая окончательный массив ranking
.
Это первоначально опубликованное решение, которое выдает ранги 1, 2, 3, 4, 4, 6 для выборочных данных (вместо 1, 2, 3, 4, 4, 5):
let dict:[String:Int] = ["team1":79, "team2":5, "team3":18, "team4":5, "team5": 82, "team6": 1]
var ranking = [(team:String,rank:Int)]()
for (_, list) in Dictionary(grouping: dict, by: { $0.value })
.sorted(by: { $0.key > $1.key }) {
let pos = ranking.count + 1
ranking.append(contentsOf: list.map { ($0.key, pos )})
}
print(ranking)
// [(team: "team5", rank: 1), (team: "team1", rank: 2),
// (team: "team3", rank: 3), (team: "team4", rank: 4),
// (team: "team2", rank: 4), (team: "team6", rank: 6)]