用元素散布列表的最优雅的方式

问题描述 投票:0回答:16

输入:

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

输出:

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

最优雅(读作:Pythonic)的书写方式是什么

intersperse

python list
16个回答
41
投票

我会自己写一个生成器,但是像这样:

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

对于 3.5+,您将需要使用此版本来正确处理空迭代。 PEP 479 - 更改生成器内部的 StopIteration 处理 更改了行为,以便生成器内的

StopInteration
错误将被视为实际错误,而不是停止迭代。让它有点不那么优雅但必要。

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

22
投票

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

19
投票

适用于序列的另一个选项:

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

8
投票

使用

more_itertools.intersperse
解决方案很简单:

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

从技术上讲,这个答案不是“写”

intersperse
,它只是使用另一个库中的它。但这可能会让其他人免于重新发明轮子。


6
投票
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']

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


3
投票

怎么样:

from itertools import chain,izip_longest

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

1
投票

不知道它是否是Pythonic,但它非常简单:

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

1
投票

我现在才想出这个,用谷歌搜索看看是否有更好的东西......恕我直言,没有:-)

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

1
投票

我相信与

yield next(iterator)
itertools.iterator_magic()
相比,这个看起来相当漂亮且易于掌握:)

def list_join_seq(seq, sep):
  for i, elem in enumerate(seq):
    if i > 0: yield sep
    yield elem

print(list(list_join_seq([1, 2, 3], 0)))  # [1, 0, 2, 0, 3]

0
投票

看起来通用且高效:

def intersperse(lst, fill=...):
    """
    >>> list(intersperse([1,2,3,4]))
    [1, Ellipsis, 2, Ellipsis, 3, Ellipsis, 4]
    """
    return chain(*zip(lst[:-1], repeat(fill)), [lst[-1]])

0
投票

您可以使用Python的列表理解:

def intersperse(iterable, element):
    return [iterable[i // 2] if i % 2 == 0 else element for i in range(2 * len(iterable) - 1)]

-1
投票

您可以做的基本且简单的事情是:

a = ['abc','def','ghi','jkl']

# my separator is : || separator ||
# hack is extra thing : --

'--|| separator ||--'.join(a).split('--')

输出:

['abc','|| separator ||','def','|| separator ||','ghi','|| separator ||','jkl']

-1
投票

这是一个可读的,不使用 itertools,只是很好的列表理解:

def intersperse(delim, items):
    items = [[delim, item] for item in items]
    return [i for is in items[1:] for i in is]

它还可以轻松扩展为每个项目添加前缀,当您获取值列表并希望将它们转换为 CLI 参数时,这会很有用。只需删除

[1:]
部分即可。您还可以通过交换第一行中的
delim
item
来简单地使其成为后缀而不是前缀。


-2
投票

这有效:

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


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

应该适用于列表或生成器。

© www.soinside.com 2019 - 2024. All rights reserved.