请选择 进入手机版|继续访问电脑版
发新帖

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

[复制链接]
4907 16

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
例如有如下列表: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}]

举报 使用道具

回复

精彩评论16

veelog  新手上路  发表于 2018-1-31 14:35:08 | 显示全部楼层
reduce 把 list 专为 dict

举报 使用道具

回复
coolair  新手上路  发表于 2018-1-31 14:56:13 | 显示全部楼层
Counter

举报 使用道具

回复
rookiebulls  新手上路  发表于 2018-1-31 14:59:26 | 显示全部楼层
用 set

举报 使用道具

回复
jxie0755  新手上路  发表于 2018-1-31 14:59:50 | 显示全部楼层
用 set 会把顺序搞没了,所以最好的办法是在 set 之后,再 sorted 一次变回 list,但是 key 用原来的 index:

print(sorted(set(a), key=a.index))

举报 使用道具

回复
zzth370  新手上路  发表于 2018-1-31 15:11:16 | 显示全部楼层
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-1-31 15:11:47 | 显示全部楼层
@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-1-31 15:21:10 | 显示全部楼层
@xpresslink 学到了,这种 sao 操作哪里学来的?只适用于 3.5 之后版本

举报 使用道具

回复
thautwarm  新手上路  发表于 2018-1-31 15:22:23 | 显示全部楼层
说实话你这需求不太对。。。

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-1-31 15:25:52 | 显示全部楼层
按照先后 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-1-31 15:34:13 | 显示全部楼层
@Binb 我感觉能写到我这个程度只能说是对 Python 初窥门径,很多是时候解决问题的能力并不是学来的,而是练功一样的积累出来的。推荐你精读《 Python Cook Book 3 》,《流畅的 Python 》,《 Python 标准库》这三本。

举报 使用道具

回复
xpresslink  新手上路  发表于 2018-1-31 15:34:34 | 显示全部楼层
@Binb 只有**item 这个语法糖是 3.5 以后的,以前版本写成 dict(item, freq=0)

举报 使用道具

回复
iwtw  新手上路  发表于 2018-1-31 15:51:02 | 显示全部楼层
@xpresslink 那请问 我要让 zhangsan sorce 的值 永远保持最新的值 如何写呢

举报 使用道具

回复
cocoakekeyu  新手上路  发表于 2018-1-31 16:01:13 | 显示全部楼层
```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-1-31 16:04:56 | 显示全部楼层
@IWTW 这样问题也问?直接多个 update 步骤就行了啊
for item in a:
    temp = b.setdefault(item['name'], {**item, 'freq': 0})
    temp.update(**item)
    temp['freq'] += 1

举报 使用道具

回复
binb  新手上路  发表于 2018-1-31 16:27:53 | 显示全部楼层
@thautwarm 嗯...我也发现了

举报 使用道具

回复
zzth370  新手上路  发表于 2018-1-31 16:51:00 | 显示全部楼层
@xpresslink 感谢指点,学习了

举报 使用道具

回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表