2016-01-21 2 views
2

Рассмотрим два списка кортежей:Комбинирование списки кортежей на основе общего элемента кортежа

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

Где len(data1) == len(data2)

Каждый кортеж содержит два элемента:

  1. список некоторых строк (т.е. [X1])
  2. A общий элемент для data1 и data2: строки '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 «s решение является хорошим , если порядок такой же, среди всех элементов в списках 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])) 
Смежные вопросы