Rommel
Rommel

Reputation: 235

Join operation of 2 lists of lists based on index

I have this 2 list of lists:

list1 = [['A', 14, 'I', 10, 20], ['B', 15, 'S', 30, 40], ['C', 16, 'F', 50, 60]]

list2 = [['A', 14, 'Y', 0, 200], ['B', 15, 'M', 0, 400], ['C', 17, 'G', 0, 600]]

(this is just a sample with only 3 lists, I have more lists but they are on the exact same format and apply same rules)

And this will be my desired output:

finalList = [['A', 14, 'Y', 10, 200], ['B', 15, 'M', 30, 400], ['C', 16, 'F', 50, 60],['C', 17, 'G', 0, 600]]

This is the rule how I compute finalList:

When list1[listindex][1] == list2[listindex][1] (ex: when 14==14), replace in list1 -> list2[2] and list2[4] (ex: 'Y' and 200) and if not just add the unmatched list from list2 to list1 as it is (like in my desired output) and also keep the ones that are in list1 that aren't matched(ex: ['C', 16, 'F', 50, 60]). How I can do this in a python 3 function? I would like a simple and straight forward function for this. Thank you so much for your time!

Upvotes: 0

Views: 103

Answers (5)

Laurent LAPORTE
Laurent LAPORTE

Reputation: 22992

Your "join" algorithm can work on each item independently and is straightforward:

def join_list(item1, item2):
    if item1[1] == item2[1]:
        result = item1[:]
        result[2] = item2[2]
        result[4] = item2[4]
        return (result,)
    return item1[:], item2[:]

This function always returns tuples: singletons in the cas of equality or couples in the general case.

You can apply this function to your two lists list1 and list2, using map() function. But the result will be a list of tuples (in fact a generator in Python 3), so you need to flatten the result:

list1 = [['A', 14, 'I', 10, 20], ['B', 15, 'S', 30, 40], ['C', 16, 'F', 50, 60]]
list2 = [['A', 14, 'Y', 0, 200], ['B', 15, 'M', 0, 400], ['C', 17, 'G', 0, 600]]

joined = [x
          for row in map(join_list, list1, list2)
          for x in row]
print(joined)

You get what you expect.

Upvotes: 0

Moses Koledoye
Moses Koledoye

Reputation: 78554

Here's one way to do it using a list comprehension:

lst =  [i for x, y in zip(list1, list2) 
          for i in (([*x[:2], y[2], x[3], y[4]],) if x[1] == y[1] else (x, y))]

print(lst)
# [['A', 14, 'Y', 10, 200], ['B', 15, 'M', 30, 400], ['C', 16, 'F', 50, 60], ['C', 17, 'G', 0, 600]]

The construction of the inner list for the matching case makes it slightly unreadable. It would be much readable in a 'deflattened' form with a for loop:

def merge_lists(list1, list2):
    lst = []
    for x, y in zip(list1, list2):
        if x[1] == y[1]:
            lst.append([*x[:2], y[2], x[3], y[4]])
        else:
            lst.extend((x, y))
    return lst

Upvotes: 0

Phil Sheard
Phil Sheard

Reputation: 2162

Here's one approach that converts the lists into a dict, and takes advantage of the fact that overlapping items from list2 will just overwrite their list1 counterparts:

combined_list = list1 + list2
final_dict = {tuple(i[:2]):tuple(i[2:]) for i in combined_list}
> {('A', 14): ('Y', 0, 200),
  ('B', 15): ('M', 0, 400),
  ('C', 16): ('F', 50, 60),
  ('C', 17): ('G', 0, 600)}
merged_list = [list(k) + list (final_dict[k]) for k in final_dict]
> [['C', 16, 'F', 50, 60],
   ['B', 15, 'M', 0, 400],
   ['C', 17, 'G', 0, 600],
   ['A', 14, 'Y', 0, 200]]

If the ordering of the list is important, you can just sort at the end or use an OrderedDict to create the merge in the first place.

Upvotes: 0

Clíodhna
Clíodhna

Reputation: 818

For working on the two lists simultaneously you can use zip() Docs Here

For example:

for value in zip(list1, list2):
       print (value[0], value[1])

will return:

['A', 14, 'I', 10, 20] ['A', 14, 'Y', 0, 200] 
['B', 15, 'S', 30, 40] ['B', 15, 'M', 0, 400]
['C', 16, 'F', 50, 60] ['C', 17, 'G', 0, 600]

so using zip you can work on both your lists at the same time.

Upvotes: 0

James
James

Reputation: 36691

You can apply all of your rules using if statements in a function.

def custom_merge(list1, list2):
    finalList = []
    for sub1, sub2 in zip(list1, list2):
        if sub1[1]==sub2[1]:
            out = sub1.copy()
            out[2] = sub2[2]
            out[4] = sub2[4]
            finalList.append(out)
        else:
            finalList.append(sub1)
            finalList.append(sub2)
    return finalList

Upvotes: 1

Related Questions