Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 给定一个字典列表,如何消除一个键的重复项,并按另一个键排序_Python_Algorithm_List_Sorting - Fatal编程技术网

Python 给定一个字典列表,如何消除一个键的重复项,并按另一个键排序

Python 给定一个字典列表,如何消除一个键的重复项,并按另一个键排序,python,algorithm,list,sorting,Python,Algorithm,List,Sorting,我正在处理一个列表,其中包含的dict对象如下所示(对象的顺序不同): 我要做的是删除重复的名称,只保留每个名称中得分最高的一个。上述清单的结果将是: [ {'name': 'Baz', 'score': 2}, {'name': 'Foo', 'score': 3}, {'name': 'Bar', 'score': 3} ] 我不确定在这里使用哪种模式(除了一个看似愚蠢的循环,不断检查当前的dict的'name'是否已经在列表中,然后检查其'score'是否高于现有

我正在处理一个
列表
,其中包含的
dict
对象如下所示(对象的顺序不同):

我要做的是删除重复的名称,只保留每个名称中得分最高的一个。上述清单的结果将是:

[
    {'name': 'Baz', 'score': 2},
    {'name': 'Foo', 'score': 3},
    {'name': 'Bar', 'score': 3}
]
我不确定在这里使用哪种模式(除了一个看似愚蠢的循环,不断检查当前的
dict
'name'
是否已经在列表中,然后检查其
'score'
是否高于现有的
'score'
一种方法是:

data = collections.defaultdict(list)
for i in my_list:
    data[i['name']].append(i['score'])
output = [{'name': i, 'score': max(j)} for i,j in data.items()]
因此,输出将是:

[{'score': 2, 'name': 'Baz'},
 {'score': 3, 'name': 'Foo'},
 {'score': 3, 'name': 'Bar'}]

分类是成功的一半

import itertools
import operator

scores = [
    {'name': 'Foo', 'score': 1},
    {'name': 'Bar', 'score': 2},
    {'name': 'Foo', 'score': 3},
    {'name': 'Bar', 'score': 3},
    {'name': 'Foo', 'score': 2},
    {'name': 'Baz', 'score': 2},
    {'name': 'Baz', 'score': 1},
    {'name': 'Bar', 'score': 1}
]

result = []
sl = sorted(scores, key=operator.itemgetter('name', 'score'),
  reverse=True)
name = object()
for el in sl:
  if el['name'] == name:
    continue
  name = el['name']
  result.append(el)
print result

这是我能想到的最简单的方法:

names = set(d['name'] for d in my_dicts)
new_dicts = []
for name in names:
    d = dict(name=name)
    d['score'] = max(d['score'] for d in my_dicts if d['name']==name)
    new_dicts.append(d)

#new_dicts
[{'score': 2, 'name': 'Baz'},
 {'score': 3, 'name': 'Foo'},
 {'score': 3, 'name': 'Bar'}]

就我个人而言,我不喜欢在问题太小时导入模块。

如果您没有听说过group by,这是一个很好的用法:

from itertools import groupby

data=[
    {'name': 'Foo', 'score': 1},
    {'name': 'Bar', 'score': 2},
    {'name': 'Foo', 'score': 3},
    {'name': 'Bar', 'score': 3},
    {'name': 'Foo', 'score': 2},
    {'name': 'Baz', 'score': 2},
    {'name': 'Baz', 'score': 1},
    {'name': 'Bar', 'score': 1}
]

keyfunc=lambda d:d['name']
data.sort(key=keyfunc)

ans=[]
for k, g in groupby(data, keyfunc):
    ans.append({k:max((d['score'] for d in g))})
print ans

>>>
[{'Bar': 3}, {'Baz': 2}, {'Foo': 3}]

这里不需要默认的dicts或set。您可以使用非常简单的dicts和list

总结字典中的最佳跑步成绩,并将结果转换回列表:

>>> s = [
    {'name': 'Foo', 'score': 1},
    {'name': 'Bar', 'score': 2},
    {'name': 'Foo', 'score': 3},
    {'name': 'Bar', 'score': 3},
    {'name': 'Foo', 'score': 2},
    {'name': 'Baz', 'score': 2},
    {'name': 'Baz', 'score': 1},
    {'name': 'Bar', 'score': 1}
]
>>> d = {}
>>> for entry in s:
        name, score = entry['name'], entry['score']
        d[name] = max(d.get(name, 0), score)

>>> [{'name': name, 'score': score} for name, score in d.items()]
[{'score': 2, 'name': 'Baz'}, {'score': 3, 'name': 'Foo'}, {'score': 3, 'name': 'Bar'}]

我想我可以在这里提出一个简单的建议:

result = dict((x['name'],x) for x in sorted(data,key=lambda x: x['score'])).values()

为了好玩,这里有一个纯功能的方法:

>>> map(dict, dict(sorted(map(sorted, map(dict.items, s)))).items())
[{'score': 3, 'name': 'Bar'}, {'score': 2, 'name': 'Baz'}, {'score': 3, 'name': 'Foo'}]

循环往复,它简单明了。当你需要“稍微”改变它时,它在六个月内简单明了,易于阅读+1这个问题有点神奇,因为它省去了一组多样而有趣的答案。这个问题有许多完全不同的解决方案,这让人着迷。我之所以把这个问题列为我的最爱,是因为它有丰富的答案集(我也会对每一个有创造性或有趣解决方案的答案进行投票)@Raymond-谢谢。我也很高兴看到这种多样性。我有几个版本,但从列表中收集了一个更干净的版本。顺便说一句,我拥有并阅读了你的书(高级Python,以防你还有其他),非常棒。我个人认为你应该再写一本书,也许是关于超高级Python或Python中的设计模式的书。+1这个答案是唯一一个不会改变数据集的答案。看起来是一致的,如果OP需要,字典可以有额外的项。使用
object()的目的是什么
这里?@nomoulus:它创建了一个在字典中找不到的新对象。
在数据中找不到任何对象(或任何其他现有对象)(尽管在本例中不是)。@Ignacio太棒了!我刚刚输入了
对象()==object()
答案是
False
,这非常方便。谢谢!如果我们使用像
{'Foo':3}
这样的数据结构而不是
[{'name':'Foo','score':3}],这个解决方案将是最优雅的
。我认为原始问题的海报应该这样做。这是我最喜欢的解决方案。我唯一要做的是将d.get(name,0)更改为d.get(name,score)。这也允许负面分数。
>>> map(dict, dict(sorted(map(sorted, map(dict.items, s)))).items())
[{'score': 3, 'name': 'Bar'}, {'score': 2, 'name': 'Baz'}, {'score': 3, 'name': 'Foo'}]