输入:
intersperse(666, ["once", "upon", "a", 90, None, "time"])
输出:
["once", 666, "upon", 666, "a", 666, 90, 666, None, 666, "time"]
如何用最优雅的方式(即使用 Pythonic 风格)编写 intersperse 函数?
我本来可以自己编写生成器,就像这样:
def joinit(iterable, delimiter):
it = iter(iterable)
yield next(it)
for x in it:
yield delimiter
yield x
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"]
chain
的参数扩展需要迭代所有s
。对于像intersperse(666, repeat(777))
这样的情况,生成器可以很好地处理。您可以通过改用chain.from_iterable(izip(...))
来解决这个问题。 - Andrew Clark另一种适用于序列的选项:
def intersperse(seq, value):
res = [value] * (2 * len(seq) - 1)
res[::2] = seq
return res
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
函数,而只是从另一个库中使用它。但这可能会避免其他人重复发明轮子。
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']
666
不应该在那里。 - Claudiudef 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风格。
len
。虽然不是一行代码,但看起来比一行代码更好看。 - Claudiu我刚想到了这个,搜了一下看看有没有更好的东西……但我认为没有 :-)
def intersperse(e, l):
return list(itertools.chain(*[(i, e) for i in l]))[0:-1]
from itertools import chain,izip_longest
def intersperse(x,y):
return list(chain(*izip_longest(x,[],fillvalue=y)))
不知道是否符合Python的风格,但它非常简单:
def intersperse(elem, list):
result = []
for e in list:
result.extend([e, elem])
return result[:-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]
next()
引发StopIteration
,生成器joinseq()
立即返回)。 - jfsjoinit
这个双关语,它既可以表示 "加入它",也可以表示 "加入可迭代对象(iterable)"。 - Claudiu