I have list like below
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]]
I want add the elements based on index if 1st sublist element match with other list sublist element
tried with below:
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
but output resulting like below:
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]]
but correct output should be:
res_list1=[['a', 1, 2, 1, 3], ['b', 2, 6, 8, 6], ['c', 2, 6, 8, 6]]
The + operator when used with a list simply adds new elements to each of the list items. In the below example we find that even a list itself can be used as a new element to be added to the existing lift. Also the existing elements in the list can be of varying length.
To get the subarray we can use slicing to get the subarray. Step 1: Run a loop till length+1 of the given list. Step 2: Run another loop from 0 to i. Step 3: Slice the subarray from j to i.
Algorithm. Step 1 : given a list. Step 2 : take one sublist which is empty initially. Step 3 : use one for loop till length of the given list.
Here's an itertools
based approach:
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]]
see @zipa's answer for a more Pythonic (efficient, short, readable, overall better) solution using dictionaries.
I will try to answer using the original structure of your own code:
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)
The problem you had is always appending to res_list1
, every iteration of the inner loop (so for every (a1,b1)
pair).
what I did to solve this is "remember" (that is - keep in a boolean variable) whether we found a match for a1
in b
, and only if not - add the original list to the result
You can define a function like this one:
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]
And call it with your lists as arguments:
add_elements(a, b)
#[['a', 1, 2, 1, 3], ['b', 2, 6, 8, 6], ['c', 2, 6, 8, 6]]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With