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
rogwan
V2EX  ›  Python

怎么把 list1 和 list2 中包含的重复字典去除,合并生成一个新的 list_all?

  •  
  •   rogwan · 2016-12-16 11:42:27 +08:00 · 4257 次点击
    这是一个创建于 2900 天前的主题,其中的信息可能已经有所发展或是发生改变。

    list1 = [{'name': 'Tom', 'score':90}, {'name': 'Jack', 'score':86}, {'name': 'Lisa', 'score':81}, {'name': 'Bill', 'score':70}]

    list2 = [{'name': 'Jack', 'score':86}, {'name': 'Bill', 'score':70}, {'name': 'Bob', 'score':48}]

    怎么把 list1 和 list2 去重合并到一个新的 list_all (保持 score 的顺序),把重合的部分拆分到一个新的 list_new:

    list_all = [{'name': 'Tom', 'score':90}, {'name': 'Jack', 'score':86}, {'name': 'Lisa', 'score':81}, {'name': 'Bill', 'score':70}, {'name': 'Bob', 'score':48}]

    list_new = [{'name': 'Jack', 'score':86}, {'name': 'Bill', 'score':70}]

    26 条回复    2016-12-21 09:50:45 +08:00
    hareandlion
        1
    hareandlion  
       2016-12-16 12:07:38 +08:00 via iPhone
    可以用 dict.update ,相同 key 的话新值会替换旧值
    hareandlion
        2
    hareandlion  
       2016-12-16 12:10:56 +08:00 via iPhone
    看错了不好意思,这种复杂结构只能手动遍历了吧
    cxyfreedom
        3
    cxyfreedom  
       2016-12-16 12:15:18 +08:00   ❤️ 1
    list_all = sorted(list1+list2, key=lambda x: x['score'], reverse=True)
    list_new = [i for i in list1 if i in list2]
    rogwan
        4
    rogwan  
    OP
       2016-12-16 12:34:13 +08:00
    @cxyfreedom 谢谢!你的 list_all 的方式不去重 ... 我在“去重”上的实现绕了好多圈,自己都看不过去了 *_*
    xiaolajiao
        5
    xiaolajiao  
       2016-12-16 12:42:52 +08:00   ❤️ 2
    去重这样: {v['name']:v for v in list1+list2}.values()
    http://stackoverflow.com/questions/11092511/python-list-of-unique-dictionaries
    weyou
        6
    weyou  
       2016-12-16 12:45:35 +08:00   ❤️ 1
    list_all = sorted([dict(i) for i in set([tuple(d.items()) for d in list1+list2])], key=lambda x: x['score'], reverse=True)
    list_new = [i for i in list1 if i in list2]

    在 @cxyfreedom 的答案上稍微修改了下,其实这么多转换,我也看不过去了
    weyou
        7
    weyou  
       2016-12-16 12:47:04 +08:00
    @xiaolajiao 这个方法好
    rogwan
        8
    rogwan  
    OP
       2016-12-16 12:47:13 +08:00
    @xiaolajiao 谢谢,我开始是用循环迭代去搞的

    list_all = []
    list1.extend(list2)
    for temp in list1:
    if temp not in list_all:
    list_all.append(temp)
    imn1
        9
    imn1  
       2016-12-16 12:51:04 +08:00
    list_new = [i for i in list1 if i in list2]
    l1 = [i for i in list1 if i not in list2]
    l2 = [i for i in list2 if i not in list1]
    list_all = list_new + l1 + l2
    print(list_all)
    imn1
        10
    imn1  
       2016-12-16 12:52:16 +08:00
    @imn1
    呃,要排序啊……忘了这个
    cxyfreedom
        11
    cxyfreedom  
       2016-12-16 12:55:58 +08:00 via iPhone
    @rogwan 第一个 all 的忘记去重了,下面那个人方法不错
    leeyiw
        12
    leeyiw  
       2016-12-16 12:58:40 +08:00
    s1 = set(list1)
    s2 = set(list2)
    list_all = list(s1.intersection(s2))
    imn1
        13
    imn1  
       2016-12-16 13:02:14 +08:00
    @leeyiw
    这个 set 不报错么?
    Yinz
        14
    Yinz  
       2016-12-16 13:03:35 +08:00
    @leeyiw unhashable type: 'dict'
    Hstar
        15
    Hstar  
       2016-12-16 13:30:08 +08:00
    遇到过差不多的问题, 我是把 list 里面每一项转成 json 然后用 set 去重再转回来
    rogwan
        16
    rogwan  
    OP
       2016-12-16 14:03:44 +08:00
    上面 @cxyfreedom @xiaolajiao @weyou 的方法推荐学习,感谢!
    fatebe
        17
    fatebe  
       2016-12-16 18:16:47 +08:00
    for ..if .. in..
    102400
        18
    102400  
       2016-12-16 20:02:02 +08:00
    ruby 可以直接 list1 | list2
    zhx1991
        19
    zhx1991  
       2016-12-17 00:13:33 +08:00
    如果要保存顺序的话好像只能循环的一个一个去看

    如果不要顺序的话 linux 下 sort + comm 可以轻松做到各种集合结果
    glogo
        20
    glogo  
       2016-12-17 03:07:05 +08:00
    ```
    temp = []

    def foo(x):
    if x not in temp:
    temp.append(x)
    return x

    print filter(foo, list1 + list2)
    ```
    practicer
        21
    practicer  
       2016-12-17 10:00:03 +08:00
    from operator import itemgetter
    from collections import Counter

    # 合并列表, 思路是先将字典转为可哈希的元组
    list_merged = [dict(t) for t in set([tuple(d.items()) for d in list1+list2])]

    # 根据字典某个值来排序, 官方库有推荐姿势 -- operator.itemgetter
    sorted(list_merged, key=lambda k: k['score'], reverse=True) # 没用 itemgetter
    sorted(list_merged, key=itemgetter('score'), reverse=True) # 使用 itemgetter

    # 保存重合项
    list_tuple = [tuple(d.items()) for d in list1+list2] # 仍先转为元组, 使其可哈希
    counts = Counter(list_tuple) # 通过 collections.Counter 查找重复项, 只接受可哈希对象
    item_dups = set([i for i in list_tuple if counts[i] > 1]) # 保留出现次数大于 1 的项, 并去重
    list_new = [dict(t) for t in item_dups] # 元组转回到字典对象
    jayli
        22
    jayli  
       2016-12-17 14:13:55 +08:00 via Android
    @leeyiw 用集合的合并
    mark06
        23
    mark06  
       2016-12-19 17:18:32 +08:00
    import numpy as np
    list_unique=list(np.unique(np.array(list1+list2)))
    mark06
        24
    mark06  
       2016-12-19 17:37:31 +08:00
    @mark06 补上交集的
    list_inter = list(np.intersect1d(list1, list2))
    182247236
        25
    182247236  
       2016-12-21 00:30:13 +08:00
    @cxyfreedom 试了下你的方法..无法去除重复,明天我也试下
    182247236
        26
    182247236  
       2016-12-21 09:50:45 +08:00
    list_new = []
    list_all = []
    list_only = []
    list1 = [{'name': 'Tom', 'score':90}, {'name': 'Jack', 'score':86}, {'name': 'Lisa', 'score':81}, {'name': 'Bill', 'score':70}]
    list2 = [{'name': 'Jack', 'score':86}, {'name': 'Bill', 'score':70}, {'name': 'Bob', 'score':48}]

    # list_new = [i for i in list1 if i in list2]
    for i in list1:
    if i in list2:
    list_new.append(i)
    else:
    list_only.append(i)

    list_all = list_only+list_new

    print(list_new)
    print(list_all)

    虽然实现了 lisr_new 和 list_all ,但是发现 lsit_all 没保持 score 的顺序,试着 list_all = sorted(list_only+list_new),结果 typeerror 。 T,T
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5929 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 03:28 · PVG 11:28 · LAX 19:28 · JFK 22:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.