2016-01-21 91 views
2

考虑的元组的两个列表:将基于一个共同的元组元素的元组的列表

data1 = [([X1], 'a'), ([X2], 'b'), ([X3], 'c')] 
data2 = [([Y1], 'a'), ([Y2], 'b'), ([Y3], 'c')] 

len(data1) == len(data2)

每个元组包含两个元素:

  1. 一些字符串列表(即[X1]
  2. A common element for data1data2:字符串'a','b'等等。

我想将它们合并为以下几点:

[('a', [X1], [Y1]), ('b', [X2], [Y2]),...] 

有谁知道我能做到这一点?

+0

@Idio,是的,我没有,但还是愿意看其他民间的想法的,有什么证明是非常有益的。 – Mrv

回答

7

可以使用zip函数和一个列表理解:

[(s1,l1,l2) for (l1,s1),(l2,s2) in zip(data1,data2)] 
5

@Kasramvd的解决方案是好如果订单是在data名单所有元素中的相同。如果不是这样,它不会考虑到这一点。

一个解决方案,确实,利用defaultdict

from collections import defaultdict 

d = defaultdict(list) # values are initialized to empty list 

data1 = [("s1", 'a'), ("s2", 'c'), ("s3", 'b')] 
data2 = [("s1", 'c'), ("s2", 'b'), ("s3", 'a')] 

for value, common in data1 + data2: 
    d[common].append(value) 

为了得到它的列表,只需在list()调用它包:

res = list(d.items()) 
print(res) 
# Prints: [('b', ['s3', 's2']), ('a', ['s1', 's3']), ('c', ['s2', 's1'])] 
1

我们可以在单个理解表达式中使用减少函数来执行此操作

from functools import reduce 
from operator import add 
[tuple([x]+reduce(add,([y[0]] for y in data1+data2 if y[1]==x))) for x in set(y[1] for y in data1+data2)] 

如果名单是大,使data1+data2施加了严格的时间或内存罚款,这可能是更好的预先计算它

combdata = data1+data2 
[tuple([x]+reduce(add,[y[0]] for y in combdata if y[1]==x))) for x in set(y[1] for y in combdata)] 

该解决方案不依赖于所有“钥匙”在这两个发生列表或订单是相同的。

如果返回顺序很重要,我们甚至可以做

sorted([tuple([x]+reduce(add,([y[0]] for y in data1+data2 if y[1]==x))) for x in set(y[1] for y in data1+data2)],key = lambda x,y=[x[0] for x in data1+data2]: y.index(x[1])) 

,以确保顺序是一样的,在最初的名单。此外,预计算data1+data2

sorted([tuple([x]+reduce(add,([y[0]] for y in combdata if y[1]==x))) for x in set(y[1] for y in combdata)],key = lambda x,y=[x[0] for x in combdata]: y.index(x[1])) 
相关问题