【问题标题】:python sort list of dicts by same key value countpython按相同的键值计数对字典列表进行排序
【发布时间】:2023-01-22 21:33:56
【问题描述】:

我有听写清单,关键“城市”可能是重复的。我需要从最重复的城市到最少的城市对这个列表进行排序。

我的字典列表:

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
#     [
#       {'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},
#     ]

这会给我几乎需要的结果,但是有 2 个带有“Lviv”的对象和 2 个带有“Zp”的对象,并且它们在结果中混合在一起(而且我认为这种方法需要太多资源)

data = sorted(
    data,
    key=lambda x: len(
        [i for i in data if i['city'] == x['city']]
    ),
    reverse=True
)
# >> data
#  [
#    {'city': 'Kyiv', 'p': 2},
#    {'city': 'Kyiv', 'p': 3},
#    {'city': 'Kyiv', 'p': 4},
#    {'city': 'Kyiv', 'p': 5},
#    {'city': 'Zp', 'p': 8},
#    {'city': 'Lviv', 'p': 7},
#    {'city': 'Zp', 'p': 9},
#    {'city': 'Lviv', 'p': 6},
#    {'city': 'Brd', 'p': 1},
#]

我想得到什么:

# >> data
#    [
#        {'city': 'Kyiv', 'p': 2},
#        {'city': 'Kyiv', 'p': 3},
#        {'city': 'Kyiv', 'p': 4},
#        {'city': 'Kyiv', 'p': 5},
#        {'city': 'Lviv', 'p': 6},
#        {'city': 'Lviv', 'p': 7},
#        {'city': 'Zp', 'p': 8},
#        {'city': 'Zp', 'p': 9},
#        {'city': 'Brd', 'p': 1},
#    ]

【问题讨论】:

  • 很多基辅在那里 :-)

标签: python sorting


【解决方案1】:
from collections import Counter
from pprint import pprint

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},
]

# find the number of occurrences of each city
cities = map(lambda d: d['city'], data)
c = Counter(cities)

# sort data according to 1) frequency of the city, 2) name of the city
sorted_data = sorted(data, key=lambda d: (c[d['city']], d['city']), reverse=True)

pprint(sorted_data)

【讨论】:

  • 感谢您的贡献,这似乎比我的方法更好。但是,不幸的是,我得到了相同的结果('Zp' 和 'Lviv' 混淆了)。但我也想按字母对它们进行分组。
  • @Vlady 你是对的,我已经编辑了我的答案来解决这个问题。
  • 是的,这正是我想要的!谢谢你。
【解决方案2】:

您需要在此处按两个键排序:

  1. 某条城市记录在data中出现的次数(只需要提取城市名称列表)
  2. 打破平局的城市名称
    >>> sorted(
        data, 
        key=lambda x: (list(y['city'] for y in data).count(x['city']), x['city']), 
        reverse=True
    )
    [
        {'city': 'Kyiv', 'p': 2}, 
        {'city': 'Kyiv', 'p': 3}, 
        {'city': 'Kyiv', 'p': 4}, 
        {'city': 'Kyiv', 'p': 5}, 
        {'city': 'Zp', 'p': 8}, 
        {'city': 'Zp', 'p': 9}, 
        {'city': 'Lviv', 'p': 6}, 
        {'city': 'Lviv', 'p': 7}, 
        {'city': 'Brd', 'p': 1}
    ]
    

【讨论】:

  • 谢谢你,Taras,看来我必须编辑我的问题。 'p' 键是 django 对象,我只是想简化我的问题(
  • 我懂了。您需要像@Fractalism 那样在我的回答中将“p”替换为“city”
  • 还是要谢谢你。
猜你喜欢
  • 1970-01-01
  • 2019-12-30
  • 1970-01-01
  • 1970-01-01
  • 2021-08-25
  • 2022-11-18
  • 2015-04-06
  • 2011-01-16
  • 1970-01-01
相关资源
最近更新 更多