簡體   English   中英

識別列表列表中共有3個元素的列表

[英]Identifying lists that have 3 elements in common in a lists of lists

我有一份清單清單。 如果存在共享前三個元素的子列表,請將它們合並到一個列表中並添加所有第四個元素。

問題最好用代碼和所需的輸出來解釋。

a_list = [['apple', 50, 60, 7],
          ['orange', 70, 50, 8],
          ['apple', 50, 60, 12]]

# output:
# [['apple', 50, 60, 19], ['orange', 70, 50, 8]]

我已經有類似問題的代碼(前一段時間由Stack Overflow中的另一個用戶給我),但我不完全理解它,所以我無法相應地修改它。 這段代碼的作用是檢查第0和第2個元素是否相同,如果是,它合並子列表,添加第1和第3個元素:

import defaultdict
data = [['42x120x1800', 50, '50x90x800', 60],
        ['42x120x1800', 8, '50x90x800', 10],
        ['2x10x800', 5, '5x9x80', 6]]

d = defaultdict(lambda :[0, 0])
for sub_list in data:
    key = (sub_list[0], sub_list[2])
    d[key][0] += sub_list[1]
    d[key][1] += sub_list[3]

new_data = [[key[0], val[0], key[1], val[1]] for key, val in d.iteritems()]
# [['2x10x800', 5, '5x9x80', 6], ['42x120x1800', 58, '50x90x800', 70]]

如何修改代碼以適應我的新問題? 如果您也能花時間並徹底解釋代碼,我真的很感激。

您可以使用相同的原則,使用前三個元素作為鍵,並使用int作為defaultdict的默認值工廠(因此您將0作為初始值):

from collections import defaultdict

a_list = [['apple', 50, 60, 7],
          ['orange', 70, 50, 8],
          ['apple', 50, 60, 12]]

d = defaultdict(int)
for sub_list in a_list:
    key = tuple(sub_list[:3])
    d[key] += sub_list[-1]

new_data = [list(k) + [v] for k, v in d.iteritems()]

如果您使用的是Python 3,則可以將其簡化為:

d = defaultdict(int)
for *key, v in a_list:
    d[tuple(key)] += v

new_data = [list(k) + [v] for k, v in d.items()]

因為您可以使用星號目標從列表中獲取所有“剩余”值,因此每個子列表主要分配給key ,最后一個值分配給v ,使循環更簡單(並且沒有.iteritems()在Python 3中的dict上的方法,因為.items()已經是一個迭代器)。

因此,我們使用一個使用0作為默認值的defaultdict ,然后對於從前3個值生成的每個鍵(作為元組,因此您可以將其用作字典鍵)對最后一個值求和。

  • 所以對於第一個項目['apple', 50, 60, 7]我們創建一個鍵('apple', 50, 60) ,在d查找它(它不存在,但defaultdict將使用int()創建一個新值0 ),並從第一個項目中添加7

  • ('orange', 70, 50)鍵和值8

  • 對於第3項,我們再次得到('apple', 50, 60)鍵,並在d[('apple', 50, 60)]預先存在的712 共19個。

然后我們將(鍵,值)對轉回列表,你就完成了。 這導致:

>>> new_data
[['apple', 50, 60, 19], ['orange', 70, 50, 8]]

需要對數據進行排序的替代實現使用itertools.groupby

from itertools import groupby
from operator import itemgetter

a_list = [['apple', 50, 60, 7],
          ['orange', 70, 50, 8],
          ['apple', 50, 60, 12]]

newlist = [list(key) + [sum(i[-1] for i in sublists)] 
    for key, sublists in groupby(sorted(a_list), key=itemgetter(0, 1, 2))]

對於相同的輸出。 如果您的數據沒有排序,這將會變慢,但知道不同的方法是很好的。

我會做這樣的事情:

>>> a_list = [['apple', 50, 60, 7],
...           ['orange', 70, 50, 8],
...           ['apple', 50, 60, 12]]
>>> 
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> from operator import itemgetter
>>> getter = itemgetter(0,1,2)
>>> for lst in a_list:
...     d[getter(lst)].extend(lst[3:])
... 
>>> d
defaultdict(<type 'list'>, {('apple', 50, 60): [7, 12], ('orange', 70, 50): [8]})
>>> print [list(k)+v for k,v in d.items()]
[['apple', 50, 60, 7, 12], ['orange', 70, 50, 8]]

然而,這並沒有給出總和。 可以通過以下方式輕松修復:

print [list(k)+[sum(v)] for k,v in d.items()]

除了允許用戶擁有超過4個項目的輸入列表(后面的元素按預期加總)之外,沒有太多理由比Martijn更優雅的解決方案更喜歡這個。 換句話說,這將通過列表:

a_list = [['apple', 50, 60, 7, 12],
          ['orange', 70, 50, 8]]

同樣。

[:3]形成鍵,以便獲得前3個元素。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM