У меня есть список, как показано ниже
a=[['a',1,2,1,3],['b',1,3,4,3],['c',1,3,4,3]]
b=[['b',1,3,4,3],['c',1,3,4,3]]
Я хочу добавить элементы на основе индекса, если 1-й элемент подсписка совпадает с другим элементом подсписка списка
попробовал с ниже:
from operator import add
res_list1=[]
for a1 in a:
for b1 in b:
if a1[0]==b1[0]:
res_list = [map(add, a1[1:], b1[1:])]
res = [[a1[0],i,j,k,l] for i,j,k,l in res_list]
res_list1.append(res[0])
else:
res_list=a1
res_list1.append(res_list)
print res_list1
но вывод, как показано ниже:
res_list1=[['a', 1, 2, 1, 3], ['a', 1, 2, 1, 3], ['b', 2, 6, 8, 6], ['b', 1, 3, 4, 3], ['c', 1, 3, 4, 3], ['c', 2, 6, 8, 6]]
но правильный вывод должен быть:
res_list1=[['a', 1, 2, 1, 3], ['b', 2, 6, 8, 6], ['c', 2, 6, 8, 6]]
Вы можете определить функцию, подобную этой:
def add_elements(a, b):
b_dict = {i[0]: i[1:] for i in b}
default = [0 for _ in a][:-1]
return [i[:1] + [sum(x) for x in zip(i[1:], b_dict.get(i[0], default))] for i in a]
И вызовите его со своими списками в качестве аргументов:
add_elements(a, b)
#[['a', 1, 2, 1, 3], ['b', 2, 6, 8, 6], ['c', 2, 6, 8, 6]]
см. ответ @zipa для более Pythonic (эффективного, короткого, читаемого, в целом лучшего) решения с использованием словарей.
Я попытаюсь ответить, используя исходную структуру вашего собственного кода:
from operator import add
a=[['a',1,2,1,3],['b',1,3,4,3],['c',1,3,4,3]]
b=[['b',1,3,4,3],['c',1,3,4,3]]
res_list1=[]
for a1 in a:
found_match = False
for b1 in b:
if a1[0]==b1[0]:
found_match = True
res_list = [map(add, a1[1:], b1[1:])]
res = [[a1[0],i,j,k,l] for i,j,k,l in res_list]
res_list1.append(res[0])
if not found_match:
res_list = a1
res_list1.append(res_list)
print(res_list1)
Проблема, с которой вы столкнулись, всегда добавлялась к res_list1
, каждой итерации внутреннего цикла (то есть для каждой пары (a1,b1)
).
что я сделал, чтобы решить эту проблему, так это "запомнить" (то есть - сохранить в логической переменной), нашли ли мы совпадение для a1
в b
, и только если нет - добавить исходный список в результат
@mnm Я взял из исходного фрагмента вопроса, что он делает, так это просто добавляет общую букву к элементам после их добавления. Есть гораздо более чистые способы сделать это (например, [a1[0]] + res_list
), но я хотел дать ОП ответ с минимальными изменениями.
Вот подход, основанный на itertools
:
from operator import itemgetter
from itertools import groupby, islice
l = sorted(a+b)
[[k] + [sum(i) for i in islice(zip(*v),1,None)] for k,v in groupby(l, key=itemgetter(0))]
# [['a', 1, 2, 1, 3], ['b', 2, 6, 8, 6], ['c', 2, 6, 8, 6]]
Это наиболее полное решение с точки зрения гибкости для случаев, когда есть несколько подсписков с одним и тем же первым элементом индекса, например, если a=[['a',8,2,1,1],['b',1,1,3,3],['c',1,3,8,3]]
и b=[['b',2,7,9,0],['c',2,8,1,4], ['a', 7,3,0,5], ['b', 6,5,0,8]]
, вывод будет [['a', 15, 5, 1, 6], ['b', 9, 13, 12, 11], ['c', 3, 11, 9, 7]]
.
@yatu: Спасибо. это мне очень помогает
@adam-er8 +1 за простое для понимания решение для опытных практиков Python.. Однако эта строка не ясна
res = [[a1[0],i,j,k,l] for i,j,k,l in res_list]
. Можете ли вы уточнить это. Благодарю.