Подтвердить что ты не робот

Python: самый элегантный способ пересечения списка с элементом

Input:

intersperse(666, ["once", "upon", "a", 90, None, "time"])

Вывод:

["once", 666, "upon", 666, "a", 666, 90, 666, None, 666, "time"]

Какой самый элегантный (читай: Pythonic) способ написать intersperse?

4b9b3361

Ответ 1

Я бы написал генератор сам, но вот так:

def joinit(iterable, delimiter):
    it = iter(iterable)
    yield next(it)
    for x in it:
        yield delimiter
        yield x

Ответ 2

itertools на помощь
- или -
Сколько функций itertools вы можете использовать в одной строке?

from itertools import chain, izip, repeat, islice

def intersperse(delimiter, seq):
    return islice(chain.from_iterable(izip(repeat(delimiter), seq)), 1, None)

Использование:

>>> list(intersperse(666, ["once", "upon", "a", 90, None, "time"])
["once", 666, "upon", 666, "a", 666, 90, 666, None, 666, "time"]

Ответ 3

Другая опция, которая работает для последовательностей:

def intersperse(seq, value):
    res = [value] * (2 * len(seq) - 1)
    res[::2] = seq
    return res

Ответ 4

Я бы пошел с простым генератором.

def intersperse(val, sequence):
    first = True
    for item in sequence:
        if not first:
            yield val
        yield item
        first = False

а затем вы можете получить свой список следующим образом:

>>> list(intersperse(666, ["once", "upon", "a", 90, None, "time"]))
['once', 666, 'upon', 666, 'a', 666, 90, 666, None, 666, 'time']

альтернативно вы можете сделать:

def intersperse(val, sequence):
    for i, item in enumerate(sequence):
        if i != 0:
            yield val
        yield item

Я не уверен, что больше pythonic

Ответ 5

def intersperse(word,your_list):
    x = [j for i in your_list for j in [i,word]]

>>> intersperse(666, ["once", "upon", "a", 90, None, "time"])
['once', 666, 'upon', 666, 'a', 666, 90, 666, None, 666, 'time', 666]

[Изменить] Исправленный код ниже:

def intersperse(word,your_list):
    x = [j for i in your_list for j in [i,word]]
    x.pop()
    return x

>>> intersperse(666, ["once", "upon", "a", 90, None, "time"])
['once', 666, 'upon', 666, 'a', 666, 90, 666, None, 666, 'time']

Ответ 6

Не знаю, если это pythonic, но это довольно просто:

def intersperse(elem, list):
    result = []
    for e in list:
      result.extend([e, elem])
    return result[:-1]

Ответ 7

Как насчет:

from itertools import chain,izip_longest

def intersperse(x,y):
     return list(chain(*izip_longest(x,[],fillvalue=y)))

Ответ 8

Это работает:

>>> def intersperse(e, l):
...    return reduce(lambda x,y: x+y, zip(l, [e]*len(l)))
>>> intersperse(666, ["once", "upon", "a", 90, None, "time"])
('once', 666, 'upon', 666, 'a', 666, 90, 666, None, 666, 'time', 666)

Если вам не нужен конечный 666, тогда return reduce(...)[:-1].

Ответ 9

Я только что придумал это сейчас, googled, чтобы увидеть, есть ли что-то лучше... и IMHO не было: -)

def intersperse(e, l):    
    return list(itertools.chain(*[(i, e) for i in l]))[0:-1]

Ответ 10

def intersperse(items, delim):
    i = iter(items)
    return reduce(lambda x, y: x + [delim, y], i, [i.next()])

Должен работать для списков или генераторов.