如果python中的每个列表中都存在一个元素,如何有效地串联列表

时间:2019-11-14 16:32:40

标签: python

我有3个列表,如下所示。

mylist1 = [["present", [1,1,1]], ["trip", [1,1,1]], ["money", [1,8,6]], ["food", [6,6,6]], ["dog", [8,6,2]]]
mylist2 = [["cat", [8,8,8]], ["trip", [5,2,8]], ["present", [8,2,6]], ["parrot", [5]], ["dogs", [8]]]
mylist3 = [["dog", [8,5]], ["trip", [8]], ["present", [6]], ["tree", [6]], ["dogs", [8]]]

我想确定这三个列表共有的单词,并将它们的值合并到一个列表中。

所以,我的输出应该如下。

[["present", [[1,1,1], [8,2,6], [6]]], ["trip", [[1,1,1], [5,2,8], [8]]]]

我目前正在执行以下操作。

lists = [mylist1, mylist2, mylist3]
mywords = []
for mylist in lists:
   for item in mylist:
     mywords.append(item[0])

my_new_list = []
for word in mywords:
   myflag = 1
   myvalues = []
   for mylist in lists:
     mytemp = []
     for item in mylist:
       if word == item[0]:
         mytemp = item[1]
         myvalues.append(mytemp)

     if len(mytemp) == 0:
         myflag = 0

   if myflag != 0:
     my_new_list.append([word,myvalues])

但是,当我每个列表中都有大约10000个元素并且要花几个小时才能运行时,这的效率真的很低。我想知道是否在python中有更有效的方法。

很高兴在需要时提供更多详细信息。

3 个答案:

答案 0 :(得分:3)

defaultdict中将common元素用作键,其中包含要合并的值的列表。
假设公共元素在一个列表中出现的次数不超过一次,即没有重复项,并且鉴于您希望它出现在每个列表中的事实,这意味着合并列表中元素的数量必须相等列表数量;每个列表一个元素。

from collections import defaultdict
d = defaultdict(list)
for L in lists:
    for k, v in L: 
        d[k].append(v)
output = [[k, v] for k, v in d.items() if len(v) == len(lists)]

如果要验证没有重复的假设,可以使用Counter

from collections import Counter
from operator import itemgetter
for L in lists:
    c = Counter(map(itemgetter(0), L)).values()
    if any(v > 1 for v in c.values()):
        print('Invalid list:', L)

答案 1 :(得分:1)

如果您知道列表的数量,则可以使用groupby(只要一个列表中只有一个单词类别)来做类似的事情(会稍好一些):

from itertools import groupby

mylist1 = [["present", [1,1,1]], ["trip", [1,1,1]], ["money", [1,8,6]], ["food", [6,6,6]], ["dog", [8,6,2]]]
mylist2 = [["cat", [8,8,8]], ["trip", [5,2,8]], ["present", [8,2,6]], ["parrot", [5]], ["dogs", [8]]]
mylist3 = [["dog", [8,5]], ["trip", [8]], ["present", [6]], ["tree", [6]], ["dogs", [8]]]

res = []
f = lambda x: x[0]
for k, g in groupby(sorted(mylist1 + mylist2 + mylist3, key=f), key=f):
    lst = list(g)
    if len(lst) == 3:
        res.append([k, [x[1] for x in lst]])

print(res)

# [['present', [[1, 1, 1], [8, 2, 6], [6]]],
#  ['trip', [[1, 1, 1], [5, 2, 8], [8]]]]

另一种方法是将您的列表转换为字典,并使用简单的查找方法,比上面的方法性能更高:

d1 = dict(mylist1)
d2 = dict(mylist2)
d3 = dict(mylist3)

print([[k, [v, d2[k], d3[k]]] for k, v in d1.items() if k in d2 and k in d3])

# [['present', [[1, 1, 1], [8, 2, 6], [6]]],
#  ['trip', [[1, 1, 1], [5, 2, 8], [8]]]]

答案 2 :(得分:1)

选中这个

from collections import defaultdict

mylist1 = [["present", [1,1,1]], ["trip", [1,1,1]], ["money", [1,8,6]], ["food", [6,6,6]], ["dog", [8,6,2]]]
mylist2 = [["cat", [8,8,8]], ["trip", [5,2,8]], ["present", [8,2,6]], ["parrot", [5]], ["dogs", [8]]]
mylist3 = [["dog", [8,5]], ["trip", [8]], ["present", [6]], ["tree", [6]], ["dogs", [8]]]

dict1 = {d[0]: d[1:] for d in mylist1}
dict2 = {d[0]: d[1:] for d in mylist2}
dict3 = {d[0]: d[1:] for d in mylist3}
#Instead of creating the dictonaries in the above fashion you can create a loop to avoid the bad styling

dd = defaultdict(list)
for d in (dict1, dict2,dict3): # Add N dict here
    for key, value in d.items():
        dd[key].append(value)

print(dd)

Output

编辑1:很抱歉,您没有注意到多余的括号,并感谢@Cristian Ciupitu注意到了。
要删除多余的方括号,请用此代码替换。

dict1 = {d[0]: d[1:][0] for d in mylist1}

希望现在输出正确。