Home > Net >  Merge 2D List Based Off of Max of Each
Merge 2D List Based Off of Max of Each

Time:03-31

I have one, two, or more lists of the same length inside of another list, like so:

list1 = [['0900', '0930', 'M', None, None, None, None]]
list2 = [['0930', '1050', 'M', None, None, None, None], ['0930', '1050', None, None, 'W', None, None]]
list3 = [['1200', '1250', 'M', None, 'W', None, None], ['1200', '1250', None, None, None, 'Th', None], ['1200', '1250', None, None, None, None, 'F']]

The first two elements are guaranteed to be the same. I'd like to merge them to one list with the max() of each other position, like so:

list1 = ['0900', '0930', 'M', None, None, None, None]
list2 = ['0930', '1050', 'M', None, 'W', None, None]
list3 = ['1200', '1250', 'M', None, 'W', 'Th', 'F']

How do I best go about that? Apparently you can't do a max() when comparing to a None.

CodePudding user response:

You can use zip() with list unpacking to make element-wise groupings. Then, to get the maximum among each group, you can check whether there exists any element that isn't None using any():

  • If such an element exists, you can get the max among all non-None elements using max() and filter().
  • If not, you can just output None.

This gives us:

[max(filter(lambda x: x is not None, sublist))
    if any(sublist) else None for sublist in zip(*lst)]

For example:

list1 = [['0900', '0930', 'M', None, None, None, None]]
list2 = [
    ['0930', '1050', 'M', None, None, None, None],
    ['0930', '1050', None, None, 'W', None, None]
]
list3 = [
    ['1200', '1250', 'M', None, 'W', None, None], 
    ['1200', '1250', None, None, None, 'Th', None],
    ['1200', '1250', None, None, None, None, 'F']
]

result = []

for lst in [list1, list2, list3]:
    result.append([max(filter(lambda x: x is not None, sublist))
        if any(sublist) else None for sublist in zip(*lst)])
    
print(result)

This outputs:

[['0900', '0930', 'M', None, None, None, None],
 ['0930', '1050', 'M', None, 'W', None, None],
 ['1200', '1250', 'M', None, 'W', 'Th', 'F']]

CodePudding user response:

Why do you need the max() of each position? If all elements except one are None, you can just take the first non-None value in the group.

def first_not_none(iterable):
    for i in iterable: 
        if i is not None: return i

Then,

>>> combined1 = [first_not_none(group) for group in zip(*list1)]  
['0900', '0930', 'M', None, None, None, None]


>>> combined2 = [first_not_none(group) for group in zip(*list2)]  
['0930', '1050', 'M', None, 'W', None, None]


>>> combined3 = [first_not_none(group) for group in zip(*list3)]
['1200', '1250', 'M', None, 'W', 'Th', 'F']
  • Related