python:在列表中穿插元素的最优雅方式

python:在列表中穿插元素的最优雅方式,python,list,Python,List,输入: 输出: intersperse(666, ["once", "upon", "a", 90, None, "time"]) 最优雅的(读入:Pythonic)编写穿插的方法是什么?我会选择一个简单的生成器 ["once", 666, "upon", 666, "a", 666, 90, 666, None, 666, "time"] 然后你可以得到如下列表: def intersperse(val, sequence): first = True for item i

输入:

输出:

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

最优雅的(读入:Pythonic)编写
穿插
的方法是什么?

我会选择一个简单的生成器

["once", 666, "upon", 666, "a", 666, 90, 666, None, 666, "time"]
然后你可以得到如下列表:

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
营救
-或-
一行中可以使用多少个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"]
如果您不想要尾随的
666
,则
返回reduce(…)[:-1]

那么:

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

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

from itertools import chain,izip_longest

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

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

def joinit(iterable, delimiter):
    it = iter(iterable)
    yield next(it)
    for x in it:
        yield delimiter
        yield x
[编辑]更正了以下代码:

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]

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

我现在刚想到这个,谷歌搜索看看是否有更好的。。。我想没有:-)

解决方案非常简单,只需使用:


从技术上讲,这个答案并不是“编写”
intersprise
,而是从另一个库中使用它。但它可能会让其他人不必重新发明轮子。

我相信与
yield next(iterator)
itertools.iterator\u magic()
one:)相比,这个看起来很好,也很容易掌握


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

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]
输出:

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

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

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


我想到了这一点,但我不喜欢在列表的末尾切片,我可以将结果初始化为列表[0],但我必须首先检查列表是否为空。[][:-1]方便地返回[]使我免于那个问题。似乎到目前为止,生成器的答案是唯一一个没有使用切片的答案。我最喜欢这个:没有切片,没有做任何特定于迭代器的事情,比如调用
len
。。这不是一款单品系列,但它看起来比单品系列更好(回到上一版本)@杰夫梅尔卡多:是的,谢谢你的评论(我想是你吗?)。它确实有效…@杰夫梅尔卡多:我知道。。。。同步问题;)但不确定这是否真的有效。。。这么多迭代器。。。。我喜欢你的解决方案:)但是知道不止一种方法(尽管Pythons的座右铭是只有一种;))很好。注意,
chain
的参数扩展需要迭代所有的
s
。这对于像
intersperse(666,repeat(777))
这样的东西来说是一个大问题,生成器很好地回答了这个问题。你应该可以用
链来解决这个问题。取而代之的是from_iterable(izip(…)
。@安德鲁:哦,我不知道。但现在我想起来有道理了。。。谢谢你,威尔在我的回答中提到这一点。是的,这比我的尝试要干净得多。恶心,这看起来是迄今为止最好的注意:第一个arg可以称为
iterable
。可以只调用函数
joinit()
。顺便说一句,您的解决方案的优点是它也适用于空序列(
next()
引发
StopIteration
,生成器
joinseq()
立即返回)。我喜欢
joinit
的双关语,意思是“加入它”和“加入它[erable]”@claudiu我喜欢你两年后回来指出:)最后一个
666
不应该有小的改进:使用“operator.concat”而不是lambda。但是这非常低效,你为每个元素调用一个函数,并进行列表添加而不是追加/扩展这是O(n²);O(n)解决方案是非常可能的,而且更简单。对不起,我想我没有注意到问题是“用元素散布列表的最快方法?”。我不知道你可以做
res[::2]=seq
。那真的很有趣。这很漂亮!我喜欢小列表的一行,但我建议使用更独特的分隔符看起来像是一根很普通的绳子,它会咬人的。请使用类似“$)($”的内容。
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']
def intersperse(items, delim):
    i = iter(items)
    return reduce(lambda x, y: x + [delim, y], i, [i.next()])
def intersperse(e, l):    
    return list(itertools.chain(*[(i, e) for i in l]))[0:-1]
>>> 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']
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]
a = ['abc','def','ghi','jkl']

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

'--|| separator ||--'.join(a).split('--')
['abc','|| separator ||','def','|| separator ||','ghi','|| separator ||','jkl']