如何按字典列表中city键重复次数排序并归组同城市项
按城市重复次数排序字典列表并保持同城市项连续
我有一个包含重复城市的字典列表,需要按城市的重复次数从多到少排序,且相同城市的项必须连续排列。给定的字典列表如下:
data = [ {'city': 'Zp', 'p': 8}, {'city': 'Kyiv', 'p': 2}, {'city': 'Lviv', 'p': 7}, {'city': 'Kyiv', 'p': 3}, {'city': 'Kyiv', 'p': 4}, {'city': 'Brd', 'p': 1}, {'city': 'Kyiv', 'p': 5}, {'city': 'Zp', 'p': 9}, {'city': 'Lviv', 'p': 6}, ]
我尝试过两种方法,但都没得到理想结果:
方法一:无效排序
data = sorted(data, key=lambda x: data.count(x['city']))
执行后列表完全没变化,原因是data.count(x['city'])统计的是整个字典对象在列表中的出现次数,每个字典都是唯一的,所以每个项的count值都是1,排序自然没有效果。
方法二:性能差且同城市项混杂
data = sorted( data, key=lambda x: len( [i for i in data if i['city'] == x['city']] ), reverse=True )
这种方法能把重复次数多的城市排到前面,但重复次数相同的城市(比如Lviv和Zp)的项会混杂在一起;而且每次排序都要遍历整个列表计算当前城市的次数,时间复杂度为O(n²),数据量大时性能很差。
正确解决方案
先统计每个城市的出现次数,再用复合排序键实现需求:
from collections import Counter data = [ {'city': 'Zp', 'p': 8}, {'city': 'Kyiv', 'p': 2}, {'city': 'Lviv', 'p': 7}, {'city': 'Kyiv', 'p': 3}, {'city': 'Kyiv', 'p': 4}, {'city': 'Brd', 'p': 1}, {'city': 'Kyiv', 'p': 5}, {'city': 'Zp', 'p': 9}, {'city': 'Lviv', 'p': 6}, ] # 一次遍历统计所有城市的出现次数,时间复杂度O(n) city_counts = Counter(item['city'] for item in data) # 复合排序键:先按次数降序,再按城市名确保同城市项连续 sorted_data = sorted(data, key=lambda x: (-city_counts[x['city']], x['city'])) print(sorted_data)
方案说明
- 高效统计次数:用
Counter只遍历一次数据就能统计出每个城市的出现次数,避免了方法二中重复遍历的性能问题。 - 复合排序键的作用:
-city_counts[x['city']]:负号让次数多的城市排在前面;x['city']:保证重复次数相同的城市会按城市名排序,同时确保同一城市的所有项连续排列(同一城市的键值完全相同,排序时会被归为一组)。
- 保留原始顺序:如果需要保持同一城市内项的原始相对顺序,Python的
sorted是稳定排序,只要复合键中同一城市的键值一致,就能满足需求。
运行后得到的结果与期望完全一致:
[ {'city': 'Kyiv', 'p': 2}, {'city': 'Kyiv', 'p': 3}, {'city': 'Kyiv', 'p': 4}, {'city': 'Kyiv', 'p': 5}, {'city': 'Lviv', 'p': 7}, {'city': 'Lviv', 'p': 6}, {'city': 'Zp', 'p': 8}, {'city': 'Zp', 'p': 9}, {'city': 'Brd', 'p': 1}, ]
内容的提问来源于stack exchange,提问作者Vlady
相关产品推荐
相关产品推荐

