推荐学习书目
› 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 · Dec 16, 2016 · 5751 views
    This topic created in 3619 days ago, the information mentioned may be changed or developed.

    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 replies  •  2016-12-21 09:50:45 +08:00
    hareandlion
    hareandlion
    Dec 16, 2016 via iPhone
    1
    可以用 dict.update ,相同 key 的话新值会替换旧值
    hareandlion
    hareandlion
    Dec 16, 2016 via iPhone
    2
    看错了不好意思,这种复杂结构只能手动遍历了吧
    cxyfreedom
    cxyfreedom
    Dec 16, 2016❤️1
    3
    list_all = sorted(list1+list2, key=lambda x: x['score'], reverse=True)
    list_new = [i for i in list1 if i in list2]
    rogwan
    rogwan
    OP
    Dec 16, 2016
    4
    @cxyfreedom 谢谢!你的 list_all 的方式不去重 ... 我在“去重”上的实现绕了好多圈,自己都看不过去了 *_*
    xiaolajiao
    xiaolajiao
    Dec 16, 2016❤️2
    5
    去重这样: {v['name']:v for v in list1+list2}.values()
    http://stackoverflow.com/questions/11092511/python-list-of-unique-dictionaries
    weyou
    weyou
    Dec 16, 2016❤️1
    6
    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
    weyou
    Dec 16, 2016
    7
    @xiaolajiao 这个方法好
    rogwan
    rogwan
    OP
    Dec 16, 2016
    8
    @xiaolajiao 谢谢,我开始是用循环迭代去搞的

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

    如果不要顺序的话 linux 下 sort + comm 可以轻松做到各种集合结果
    glogo
    glogo
    Dec 17, 2016
    20
    ```
    temp = []

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

    print filter(foo, list1 + list2)
    ```
    practicer
    practicer
    Dec 17, 2016
    21
    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
    jayli
    Dec 17, 2016 via Android
    22
    @leeyiw 用集合的合并
    mark06
    mark06
    Dec 19, 2016
    23
    import numpy as np
    list_unique=list(np.unique(np.array(list1+list2)))
    mark06
    mark06
    Dec 19, 2016
    24
    @mark06 补上交集的
    list_inter = list(np.intersect1d(list1, list2))
    182247236
    182247236
    Dec 21, 2016
    25
    @cxyfreedom 试了下你的方法..无法去除重复,明天我也试下
    182247236
    182247236
    Dec 21, 2016
    26
    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
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1018 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 51ms · UTC 22:54 · PVG 06:54 · LAX 14:54 · JFK 17:54
    ♥ Do have faith in what you're doing.