Home > Back-end >  How do you merge two lists and return them as a tuple in a new list?
How do you merge two lists and return them as a tuple in a new list?

Time:10-31

rules: If one list is shorter than the other, the last element of the shorter list should be repeated as often as necessary. If one or both lists are empty, the empty list should be returned.

merge([0, 1, 2], [5, 6, 7])

should return [(0, 5), (1, 6), (2, 7)]

merge([2, 1, 0], [5, 6])

should return [(2, 5), (1, 6), (0, 6)]

merge([ ], [2, 3])

should return []

this is what I've written so far

def merge(a, b):
mergelist = []
for pair in zip(a, b):
    for item in pair :
        mergelist.append(item )
return mergelist

print(merge([0, 1, 2], [5, 6]))

CodePudding user response:

I'd use zip_longest:

from itertools import zip_longest

def merge(a, b):
    return list(a and b and zip_longest(a, b, fillvalue=min(a, b, key=len)[-1]))

Same thing, different style:

def merge(a, b):
    if a and b:
        short = min(a, b, key=len)
        return list(zip_longest(a, b, fillvalue=short[-1]))
    return []

CodePudding user response:

You need to manually append each tuple in the return list as you need to check if the length of the second list accordingly. This is one way of solving this

def merge(l1, l2):
    new = []
    for i in range(len(l1)):
        if i > len(l2)-1:
            s2 = l2[len(l2)-1] # use the last element of second list if there are no more elements
        else:
            s2 = l2[i]
        new.append(l1[i], s2)
    return new

"""
>>> merge([0,1,2],[5,6,7])
[(0, 5), (1, 6), (2, 7)]
>>> merge([2,1,0],[5,6])
[(2, 5), (1, 6), (0, 6)]
>>> merge([],[2,3])
[]
"""

CodePudding user response:

Thanks for asking the question. I tried to amend your code as it is always easier to understand our own code. Please find modifications

def merge(a, b):
    mergelist = []
    if not a or not b:
        return []
    elif len(a) > len(b):
        occ = len(a)-len(b)
        b.extend([b[len(b)-1] for i in range(occ)])
    elif len(a) < len(b):

        occ = len(b)-len(a)
        a.extend([a[len(a)-1] for i in range(occ)])

    for pair in zip(a, b):
        mergelist.append(pair)
    return mergelist

print(merge(l,l1))

CodePudding user response:

This is actually somewhat tricky. You would think something simple like this would work:

def merge(a, b):
    # use iterator to keep iterations state after zip
    a, b = iter(a), iter(b)
    rtrn = list(zip(a, b))
    try:
        taila, tailb = rtrn[-1]
    except IndexError: # one or both empty
        return rtrn
    # only one of these loops will run, draining the longer input list
    rtrn.extend((ai, tailb) for ai in a)
    rtrn.extend((taila, bi) for bi in b)
    return rtrn

Here the trick is to use an iterator, not an iterable. An iterator keeps its state. So after the zip, both iterators should still point at the place where zip stopped. However, this does not work if b is the shorter list. Because then zip will have removed one value from a and will discard it. You have to be careful to avoid this. The easiest way is to just materialize two lists and deal with the length differences explicitely.

def merge(a, b):
    # ensure that we have lists, not anything else like iterators, sets, etc
    a, b = list(a), list(b)
    rtrn = list(zip(a, b))
    try:
        taila, tailb = rtrn[-1]
    except IndexError: # one or both empty
        return rtrn
    rtrnlen = len(rtrn)
    # only one of these loops will run, draining the longer input list
    # You could also use itertools.zip_longest for this
    rtrn.extend((ai, tailb) for ai in a[rtrnlen:])
    rtrn.extend((taila, bi) for bi in b[rtrnlen:])
    return rtrn

CodePudding user response:

from itertools import zip_longest

def merge(a,b):
    if len(a) > len(b):
        return list((zip_longest(a,b,fillvalue=b[-1])))
    else:
        return list((zip_longest(a,b,fillvalue=a[-1])))`

for example

 a = [2,3,5]
 b = [1,2]
 merge(a,b)
 [(2, 1), (3, 2), (5, 2)]

Link to documentation for zip_longest

https://docs.python.org/3/library/itertools.html#itertools.zip_longest

  • Related