V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Binb
V2EX  ›  Python

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

  •  
  •   Binb · 2018-01-27 14:47:23 +08:00 · 5072 次点击
    这是一个创建于 2274 天前的主题,其中的信息可能已经有所发展或是发生改变。

    例如有如下列表: 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 条回复    2018-01-29 15:41:58 +08:00
    veelog
        1
    veelog  
       2018-01-27 14:51:44 +08:00 via iPhone   ❤️ 1
    reduce 把 list 专为 dict
    coolair
        2
    coolair  
       2018-01-27 14:52:25 +08:00 via Android   ❤️ 1
    Counter
    rookiebulls
        3
    rookiebulls  
       2018-01-27 21:59:28 +08:00 via iPhone
    用 set
    jxie0755
        4
    jxie0755  
       2018-01-28 09:58:01 +08:00   ❤️ 1
    用 set 会把顺序搞没了,所以最好的办法是在 set 之后,再 sorted 一次变回 list,但是 key 用原来的 index:

    print(sorted(set(a), key=a.index))
    zzth370
        5
    zzth370  
       2018-01-28 11:03:21 +08:00   ❤️ 1
    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
        6
    xpresslink  
       2018-01-28 20:20:17 +08:00   ❤️ 1
    @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
        7
    Binb  
    OP
       2018-01-28 21:18:04 +08:00
    @xpresslink 学到了,这种 sao 操作哪里学来的?只适用于 3.5 之后版本
    thautwarm
        8
    thautwarm  
       2018-01-29 03:28:41 +08:00   ❤️ 2
    说实话你这需求不太对。。。

    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
        9
    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
        10
    xpresslink  
       2018-01-29 10:02:59 +08:00
    @Binb 我感觉能写到我这个程度只能说是对 Python 初窥门径,很多是时候解决问题的能力并不是学来的,而是练功一样的积累出来的。推荐你精读《 Python Cook Book 3 》,《流畅的 Python 》,《 Python 标准库》这三本。
    xpresslink
        11
    xpresslink  
       2018-01-29 10:09:56 +08:00
    @Binb 只有**item 这个语法糖是 3.5 以后的,以前版本写成 dict(item, freq=0)
    IWTW
        12
    IWTW  
       2018-01-29 11:16:11 +08:00
    @xpresslink 那请问 我要让 zhangsan sorce 的值 永远保持最新的值 如何写呢
    cocoakekeyu
        13
    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
        14
    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
        15
    Binb  
    OP
       2018-01-29 13:58:13 +08:00
    @thautwarm 嗯...我也发现了
    zzth370
        16
    zzth370  
       2018-01-29 15:41:58 +08:00
    @xpresslink 感谢指点,学习了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   934 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 20:27 · PVG 04:27 · LAX 13:27 · JFK 16:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.