Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding sublists elements based on indexing by condition in python

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]]
like image 984
learningstudent Avatar asked Jun 13 '19 07:06

learningstudent


People also ask

How do you add numbers to a sublist in Python?

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.

How do you make a sub list in Python?

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.

How do you create a sublist from the main list in Python?

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.


3 Answers

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]]
like image 82
yatu Avatar answered Oct 12 '22 13:10

yatu


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

like image 29
Adam.Er8 Avatar answered Oct 12 '22 12:10

Adam.Er8


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]]
like image 23
zipa Avatar answered Oct 12 '22 11:10

zipa