Tatu Bogdan
Tatu Bogdan

Reputation: 596

Merge list of lists in python 3

I have this 2 lists of list:

list1= [['user1', 186, 'Feb 2017, Apr 2017', 550, 555], ['user2', 282, 'Mai 2017', 0, 3579], ['user3', 281, 'Mai 2017', 10, 60]]

list2= [['user1', 186, 'Feb 2017, Mar 2017, Mai 2017', 0, 740],['user2', 282, 'Feb 2017', 0, 1000], ['user4', 288, 'Feb 2017', 60, 10]]

And I desire to output this:

desiredlist =[['user1', 186, 'Feb 2017, Mar 2017, Mai 2017', 550, 740], ['user2', 282, 'Feb 2017', 0, 1000], ['user3', 281, 'Mai 2017', 10, 0], ['user4', 288, 'Feb 2017', 60, 10]]

For that I have this function:

def mergesafirmacheta(list1,list2):
    desiredlist = []
    for id, n1, dates, n2, n3 in list1:
        counter = 0
        for list_2 in list2:
            if n1 == list_2[1]:
                desiredlist.append(list_2[:3] + [n2, list_2[4]])
            else:
                   counter += 1
                   if counter == len(list2):
                       desiredlist.append([id, n1, dates, n2, 0])
    print (desiredlist)

But this will output just this:

desiredlist =[['user1', 186, 'Feb 2017, Mar 2017, Mai 2017', 550, 740], ['user2', 282, 'Feb 2017', 0, 1000], ['user3', 281, 'Mai 2017', 10, 0]]

^^ user4 is missing (check my desired output), I can see why from my function, I try to add this after my first is statement:

elif list_2[1] != n1:
    desiredlist.append(list_2)

But this won't work, this are the rules to compute the desired list:

When list2[1] == list1[1] (example 186 == 186) append to my desiredlist list2[0], list2[1], list2[2], list1[3], list2[4], if you have a list1[1] that is not in list2 lists change append to desiredlist list1[0], list1[1], list1[2], list1[3], 0, and if a list2[1] that is not in list1 lists append to desiredlist list2[0], list2[1], list2[2], list2[3], list2[4]. This is a bit hard to fallow but I think is much easier to check for my desired output and what I actually output right now.

Upvotes: 1

Views: 297

Answers (3)

Kruupös
Kruupös

Reputation: 5484

I managed to do what you intended by changing your format. I convert all your sublists into dict with the key user.

Because it easier to merge dict and the order of user in your sublists doesn't matter.

The last steps is to iterate over the merged dict of list1 and list2 and do your special operation. As I understood, is to take the before last number of list1 and merge it with list2. Then you recreate your desired sublist.

from itertools import chain
from collections import defaultdict

list1 = [['user1', 186, 'Feb 2017, Apr 2017', 550, 555], ['user2', 282, 'Mai 2017', 0, 3579], ['user3', 281, 'Mai 2017', 10, 60]]
list2 = [['user1', 186, 'Feb 2017, Mar 2017, Mai 2017', 0, 740],['user2', 282, 'Feb 2017', 0, 1000], ['user4', 288, 'Feb 2017', 60, 10]]

# Transform list to dict with key as 'userN'
def to_dict(lst): return {x[0]: x[1:] for x in lst} 

# Now create a dict that combined list of user1..N+1
tmp_dict = defaultdict(list)
for k, v in chain(to_dict(list1).items(), to_dict(list2).items()):
  tmp_dict[k].append(v)

desired_output = []
for k, v in tmp_dict.items():
  if len(v) == 2:
    v[1][-2] = v[0][-2] # Take the before last of list1 to remplace with before last one of list2
    desired_output.append([k] + v[1])
  else:
    desired_output.append([k] + v[0])

print(desired_output)

Output:

[['user1', 186, 'Feb 2017, Mar 2017, Mai 2017', 550, 740], ['user2', 282, 'Feb 2017', 0, 1000], ['user3', 281, 'Mai 2017', 10, 60], ['user4', 288, 'Feb 2017', 60, 10]]

EDIT

It seems I make a mistake and your list1 have to check all the content of list2, in that case you should make a dict of list2 first and apply your specific condition after. eg:

from itertools import chain

list1 = [['user1', 186, 'Feb 2017, Apr 2017', 550, 555], ['user2', 282, 'Mai 2017', 0, 3579], ['user3', 281, 'Mai 2017', 10, 60]]
list2 = [['user1', 186, 'Feb 2017, Mar 2017, Mai 2017', 0, 740],['user2', 282, 'Feb 2017', 0, 1000], ['user4', 288, 'Feb 2017', 60, 10]]

# Transform list to dict with key as 'userN'
def to_dict(lst): return {x[0]: x[1:] for x in lst} 

# First, transfrom list2 to dict
list2_dict = {}
for k, v in to_dict(list2).items():
  list2_dict[k] = v

# Then iterate on list1 to compare
desired_output = []
for k, v in to_dict(list1).items():
  if k in list2_dict: # key of list1 exists in list2
    list2_dict[k][-2] = v[-2] # replace value
    desired_output.append([k] + list2_dict[k]) # Then add list2
    list2_dict.pop(k) # And remove it from old dict
  else: # list1 does not exists in list2
    v[-1] = 0 # Set last element to zero
    desired_output.append([k] + v)

for k, v in list2_dict.items(): # Now add elements present only in list2
  desired_output.append([k] + v)

print(desired_output)

output:

[['user1', 186, 'Feb 2017, Mar 2017, Mai 2017', 550, 740], ['user2', 282, 'Feb 2017', 0, 1000], ['user3', 281, 'Mai 2017', 10, 0], ['user4', 288, 'Feb 2017', 60, 10]]

Note: we can get rid of defaultdict since the same key is not being to be added twice.

Upvotes: 1

P.Madhukar
P.Madhukar

Reputation: 464

Use this code :

list1= [['user1', 186, 'Feb 2017, Apr 2017', 550, 555], ['user2', 282, 'Mai 2017', 0, 3579], ['user3', 281, 'Mai 2017', 10, 60]]

list2= [['user1', 186, 'Feb 2017, Mar 2017, Mai 2017', 0, 740],['user2', 282, 'Feb 2017', 0, 1000], ['user4', 288, 'Feb 2017', 60, 10]]

final_list = []
for l1_data, l2_data in zip(list1, list2):
    if l1_data[0] == l2_data[0]:
        for index, elem in enumerate(l2_data):
            if index+1 <= len(l1_data):
                if not elem and l1_data[index]:
                    l2_data[index] = l1_data[index]                    
    else: final_list.append(l1_data)
    final_list.append(l2_data)
print final_list

Ouptut:

[['user1', 186, 'Feb 2017, Mar 2017, Mai 2017', 550, 740], ['user2', 282, 'Feb 2017', 0, 1000], ['user3', 281, 'Mai 2017', 10, 60], ['user4', 288, 'Feb 2017', 60, 10]]

Upvotes: 1

Tan Wei Lian
Tan Wei Lian

Reputation: 112

you can iterate through the distinct second element of both list combined:

for n in set([item[1] for item in list1+list2]):

then you can decide to add to your desired list by looking up n in both list

Upvotes: 0

Related Questions