我能够对字符串和整数的字典进行排名。 但是我的解决方案看起来并不聪明又“笨拙”
问题在于,更多的团队与“第2团队”和“第4团队”具有相同的分数和相同的排名
ex dic input
var dict:[String:Int] = ["team1":79,"team2":5, "team3":18, "team4":5, "team5": 82, "team6":1]
输出
[(团队:“ team5”,等级:1),(团队:“ team1”,等级:2),(团队:“ team3”, 排名:3),(团队:“ team2”,排名:4),(团队:“ team4”,排名:4),(团队:“ team6”,排名:5)]
代码:
var ris = [(team:String,rank:Int)]()
var pos = 1
let sorted = dict.sorted(by:{$0.value > $1.value})
print(sorted)
for (i, element) in sorted.enumerated() {
if i == 0 || element.value == sorted[i-1].value {
}
else {
pos += 1
}
ris.append((team:element.key,rank:pos))
}
let ranking = ris.sorted(by:{$0.rank < $1.rank})
print(ranking)
打印:
[(团队:“ team5”,等级:1),(团队:“ team1”,等级:2),(团队:“ team3”, 排名:3),(团队:“ team2”,排名:4),(团队:“ team4”,排名:4),(团队:“ team6”,排名:5)]
好的,但是我敢肯定,使用某些排序的,贴图的地图贴图等,我会丢失更好的东西
有人吗?
答案 0 :(得分:2)
您可以通过首先在字典中将具有相同分数的团队分组来简化它。然后对字典排序(根据得分递减),对它进行枚举(获取偏移量)并建立排名列表:
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、5、5)生成了排名1、2、3、4、4、6:
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)]
答案 1 :(得分:1)
是的,有一个更简单的解决方案:)
let teamScores = [
"team1":79,
"team2":5,
"team3":18,
"team4":5,
"team5": 82
]
let teamRanks = teamScores
.sorted(by: { $0.value > $1.value})
.enumerated()
.map { (offset: Int, pair: (team: String, score: Int)) -> (team: String, rank: Int) in
let rank = offset + 1
return (team: pair.team, rank: rank)
}
print(teamRanks)
如果您希望将平局分数给予相同的排名,则类型签名会显得有些毛茸茸,但是想法很相似:
let teamScores = [
"team1":79,
"team2":5,
"team3":18,
"team4":5,
"team5": 82
]
let teamRanks = Dictionary(grouping: teamScores, by: { $0.value })
.sorted(by: { $0.key > $1.key })
.enumerated()
.flatMap { (
offset: Int,
ranks: (
commonScore: Int,
teamScores: [(key: String, value: Int)]
)
) -> [(team: String, rank: Int)] in
let rank = offset + 1
return ranks.teamScores.map { (team: $0.key, rank: rank) }
}
print(teamRanks)