Как объединить два списка и вернуть их как кортеж в новом списке?

#python #list #merge #tuples

Вопрос:

Правила: Если один список короче другого, последний элемент более короткого списка следует повторять так часто, как это необходимо. Если один или оба списка пусты, должен быть возвращен пустой список.

слияние([0, 1, 2], [5, 6, 7])

должен вернуться [(0, 5), (1, 6), (2, 7)]

слияние([2, 1, 0], [5, 6])

должен вернуться [(2, 5), (1, 6), (0, 6)]

слияние([ ], [2, 3])

должен вернуться []

это то, что я написал до сих пор

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

печать (слияние([0, 1, 2], [5, 6]))

Комментарии:

1. Используйте встроенную функцию zip

2. Вам нужно просто list(zip(a, b)) ?

3. zip уже в его коде. и ожидаемые результаты немного странные

4. Итак, вы ожидаете, что выходные данные будут иметь длину первого списка, а последний элемент второго списка будет повторяться, если он короче? Что, если он пуст? Или это что-то еще? Пожалуйста, уточните правила.

5. Если один список короче другого, последний элемент более короткого списка следует повторять так часто, как это необходимо. Если один или оба списка пусты, должен быть возвращен пустой список.

Ответ №1:

Спасибо, что задали вопрос. Я попытался внести изменения в ваш код, поскольку всегда легче понять наш собственный код. Пожалуйста, найдите изменения

 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))
 

Ответ №2:

Вам нужно вручную добавить каждый кортеж в возвращаемый список, так как вам нужно проверить, соответствует ли длина второго списка соответствующей. Это один из способов решения этой проблемы

 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])
[]
"""
 

Ответ №3:

На самом деле это несколько сложно. Можно подумать, что сработает что-то простое, подобное этому:

 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
 

Здесь хитрость заключается в использовании итератора, а не итерируемого. Итератор сохраняет свое состояние. Таким образом, после zip оба итератора все равно должны указывать на место, где zip остановился.
Однако это не работает, если b — более короткий список. Потому что тогда zip удалит одно значение из a и отбросит его. Вы должны быть осторожны, чтобы избежать этого.
Самый простой способ — просто материализовать два списка и явно разобраться с различиями в длине.

 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
 

Ответ №4:

Я бы использовал 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]))
 

То же самое, другой стиль:

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

Ответ №5:

 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])))`
 

например

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

Ссылка на документацию для zip_longest

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

Комментарии:

1. слияние (a, b) должно возвращать [(2, 1), (3, 2), (5, 2)]

2. @newbie я исправил код для этого условия