Python 列表中字典元素(name 相等的)去重

2018-01-27 14:47:23 +08:00
 Binb

例如有如下列表: a = [ {'name':'zhangsan', 'score':20}, {'name':'lisi', 'score':25}, {'name':'zhangsan', 'score':30} ]

想要结果: a = [ {'name': 'zhangsan', 'score':20, 'freq':2}, {'name': 'lisi', 'score': 25, 'freq':1} ]

5271 次点击
所在节点    Python
16 条回复
veelog
2018-01-27 14:51:44 +08:00
reduce 把 list 专为 dict
coolair
2018-01-27 14:52:25 +08:00
Counter
rookiebulls
2018-01-27 21:59:28 +08:00
用 set
jxie0755
2018-01-28 09:58:01 +08:00
用 set 会把顺序搞没了,所以最好的办法是在 set 之后,再 sorted 一次变回 list,但是 key 用原来的 index:

print(sorted(set(a), key=a.index))
zzth370
2018-01-28 11:03:21 +08:00
a = [{'name': 'zhangsan', 'score': 20}, {'name': 'lisi', 'score': 25}, {'name': 'zhangsan', 'score': 30}]
b = [{'name': item['name']} for item in a]
c = {item['name'] for item in a}
d = [{'name': item['name'], 'score': item['score'], 'freq': b.count({'name': item['name']})} for item in a]
e = []
for item in d:
if item['name'] in c:
e.append(item)
c.remove(item['name'])
print(e)

效果能实现,但感觉代码有点臃肿
xpresslink
2018-01-28 20:20:17 +08:00
@zzth370 确实有点,关键是用 count 会效率低的吓人。
真心看不下去了,我又写了一个。

#!/usr/bin/env python3.6
# -*- coding: utf-8 -*-

from collections import OrderedDict

a = [ {'name':'zhangsan', 'score': 20}, {'name':'lisi', 'score':25}, {'name':'zhangsan', 'score':30} ]

b = OrderedDict()

for item in a:
b.setdefault(item['name'], {**item, 'freq':0})['freq'] += 1

print(b.values())
# odict_values([{'name': 'zhangsan', 'score': 20, 'freq': 2}, {'name': 'lisi', 'score': 25, 'freq': 1}])
Binb
2018-01-28 21:18:04 +08:00
@xpresslink 学到了,这种 sao 操作哪里学来的?只适用于 3.5 之后版本
thautwarm
2018-01-29 03:28:41 +08:00
说实话你这需求不太对。。。

a = [ {'name':'zhangsan', 'score':20}, {'name':'lisi', 'score':25}, {'name':'zhangsan', 'score':30} ]的结果怎么看怎么是
[ ({'name': 'zhangsan', 'score':20}, 2), ({'name': 'lisi', 'score': 25}, 1) ] 正常。

所以我比较偏向
[(a[idx], count) for _, idx, count in zip(*np.unique(list(map(lambda _: _['name'], a)), return_index=True, return_counts=True))]

当然你喜欢
[{**a[idx], 'freq':count} for _, idx, count in zip(*np.unique(list(map(lambda _: _['name'], a)), return_index=True, return_counts=True))]
thautwarm
2018-01-29 03:31:37 +08:00
按照先后 index 发现的顺序
[{**a[idx], 'freq':count} for _, idx, count in sorted(zip(*np.unique(list(map(lambda _: _['name'], a)), return_index=True, return_counts=True)), key=lambda x: x[1])]
xpresslink
2018-01-29 10:02:59 +08:00
@Binb 我感觉能写到我这个程度只能说是对 Python 初窥门径,很多是时候解决问题的能力并不是学来的,而是练功一样的积累出来的。推荐你精读《 Python Cook Book 3 》,《流畅的 Python 》,《 Python 标准库》这三本。
xpresslink
2018-01-29 10:09:56 +08:00
@Binb 只有**item 这个语法糖是 3.5 以后的,以前版本写成 dict(item, freq=0)
IWTW
2018-01-29 11:16:11 +08:00
@xpresslink 那请问 我要让 zhangsan sorce 的值 永远保持最新的值 如何写呢
cocoakekeyu
2018-01-29 12:24:32 +08:00
```python
def dedupe2(itmes, key=None):
seen = set()
for item in items:
val = item if key is None else key(item)
if val not in seen:
yield item
seen.add(item)
```

key 换成 operator.getitem('name')
xpresslink
2018-01-29 12:44:36 +08:00
@IWTW 这样问题也问?直接多个 update 步骤就行了啊
for item in a:
temp = b.setdefault(item['name'], {**item, 'freq': 0})
temp.update(**item)
temp['freq'] += 1
Binb
2018-01-29 13:58:13 +08:00
@thautwarm 嗯...我也发现了
zzth370
2018-01-29 15:41:58 +08:00
@xpresslink 感谢指点,学习了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/426380

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX