斯威夫特排名字典

时间:2019-06-09 10:15:55

标签: ios swift iphone swift5

我能够对字符串和整数的字典进行排名。 但是我的解决方案看起来并不聪明又“笨拙”

问题在于,更多的团队与“第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)]

好的,但是我敢肯定,使用某些排序的,贴图的地图贴图等,我会丢失更好的东西

有人吗?

2 个答案:

答案 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)
  • 您对团队得分进行排序,以便最高得分排在第一位
  • 枚举顺序,以便您可以访问索引(其中0是最好的团队,1是第二好的团队,...)
  • 在元素上映射会重命名元组成员,并向所有偏移量添加一个(形成基于1的索引)

如果您希望将平局分数给予相同的排名,则类型签名会显得有些毛茸茸,但是想法很相似:

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)