怎么把 list1 和 list2 中包含的重复字典去除,合并生成一个新的 list_all? - V2EX
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 4794 次点击
    这是一个创建于 3222 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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
    imn  
       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     Solana     900 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 22:34 PVG 06:34 LAX 15:34 JFK 18:34
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86