Использование zip () в неравных списках, но избегать возврата - PullRequest
0 голосов
/ 25 апреля 2019

Существует существующая ветка об этом Извлечение неравных списков в python в список, который не удаляет ни один элемент из более длинного списка, заархивированного

Но это не совсем так, я после,Вместо возврата «Нет» мне нужно скопировать запись из предыдущего списка.

Возможно ли это?

Спасибо, что посмотрели на мою проблему.

a = ["bottle","water","sky"]
b = ["red", "blue"]
for i in itertools.izip_longest(a,b):
    print i

#result
# ('bottle', 'red')
# ('water', 'blue')
# ('sky', None) 

# What I want on the third line is
# ('sky', 'blue')

Ответы [ 2 ]

1 голос
/ 26 апреля 2019

itertools.izip_longest принимает необязательный аргумент fillvalue, который предоставляет значение, которое используется после исчерпания более короткого списка. fillvalue по умолчанию None, что показывает поведение, которое вы показываете в своем вопросе, но вы можете указать другое значение, чтобы получить желаемое поведение:

    fill = a[-1] if (len(a) < len(b)) else b[-1]
    for i in itertools.izip_longest(a, b, fillvalue=fill):
        print i

(Очевидно, что если один и тот же список всегда короче, то выбрать символ заполнения еще проще.)

0 голосов
/ 26 апреля 2019

Вы можете chain более короткий список с repeat его последнего значения. Затем, используя обычный izip, результатом будет длина более длинного списка:

from itertools import izip, repeat, chain

def izip_longest_repeating(seq1, seq2):
    if len(seq1) < len(seq2):
        repeating = seq1[-1]
        seq1 = chain(seq1, repeat(repeating))
    else:
        repeating = seq2[-1]
        seq2 = chain(seq2, repeat(repeating))
    return izip(seq1, seq2)   

print(list(izip_longest_repeating(a, b)))
#  [('bottle', 'red'), ('water', 'blue'), ('sky', 'blue')]    

А вот версия, которая должна работать для любых итераций:

from itertools import izip as zip # Python2 only

def zip_longest_repeating(*iterables):
    iters = [iter(i) for i in iterables]
    sentinel = object() 
    vals = tuple(next(it, sentinel) for it in iters)
    if any(val is sentinel for val in vals):
        return
    yield vals
    while True:
        cache = vals
        vals = tuple(next(it, sentinel) for it in iters)
        if all(val is sentinel for val in vals):
            return
        vals = tuple(old if new is sentinel else new for old, new in zip(cache, vals))
        yield vals

list(zip_longest_repeating(['a'], ['b', 'c'], ['d', 'r', 'f']))
#  [('a', 'b', 'd'), ('a', 'c', 'r'), ('a', 'c', 'f')]
...