Input:
intersperse(666, ["once", "upon", "a", 90, None, "time"])
Output:
["once", 666, "upon", 666, "a", 666, 90, 666, None, 666, "time"]
What’s the most elegant (read: Pythonic) way to write intersperse?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
I would have written a generator myself, but like this:
def joinit(iterable, delimiter):
it = iter(iterable)
yield next(it)
for x in it:
yield delimiter
yield x
Method 2
itertools to the rescue
– or –
How many itertools functions can you use in one line?
from itertools import chain, izip, repeat, islice
def intersperse(delimiter, seq):
return islice(chain.from_iterable(izip(repeat(delimiter), seq)), 1, None)
Usage:
>>> list(intersperse(666, ["once", "upon", "a", 90, None, "time"]) ["once", 666, "upon", 666, "a", 666, 90, 666, None, 666, "time"]
Method 3
Another option that works for sequences:
def intersperse(seq, value):
res = [value] * (2 * len(seq) - 1)
res[::2] = seq
return res
Method 4
Solution is trivial using 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']
Technically, this answer isn’t “writing” intersperse, it’s just using it from another library. But it might save others from having to reinvent the wheel.
Method 5
I would go with a simple generator.
def intersperse(val, sequence):
first = True
for item in sequence:
if not first:
yield val
yield item
first = False
and then you can get your list like so:
>>> list(intersperse(666, ["once", "upon", "a", 90, None, "time"])) ['once', 666, 'upon', 666, 'a', 666, 90, 666, None, 666, 'time']
alternatively you could do:
def intersperse(val, sequence):
for i, item in enumerate(sequence):
if i != 0:
yield val
yield item
I’m not sure which is more pythonic
Method 6
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]
[Edit] Corrected code below:
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']
Method 7
How about:
from itertools import chain,izip_longest
def intersperse(x,y):
return list(chain(*izip_longest(x,[],fillvalue=y)))
Method 8
The basic and easy you could do is:
a = ['abc','def','ghi','jkl']
# my separator is : || separator ||
# hack is extra thing : --
'--|| separator ||--'.join(a).split('--')
output:
['abc','|| separator ||','def','|| separator ||','ghi','|| separator ||','jkl']
Method 9
Dunno if it’s pythonic, but it’s pretty simple:
def intersperse(elem, list):
result = []
for e in list:
result.extend([e, elem])
return result[:-1]
Method 10
I just came up with this now, googled to see if there was something better… and IMHO there wasn’t 🙂
def intersperse(e, l):
return list(itertools.chain(*[(i, e) for i in l]))[0:-1]
Method 11
I believe this one looks pretty nice and easy to grasp compared to the yield next(iterator) or itertools.iterator_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]
Method 12
This works:
>>> 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)
If you don’t want a trailing 666, then return reduce(...)[:-1].
Method 13
Seems general and efficient:
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]])
Method 14
You can use Python’s list comprehension:
def intersperse(iterable, element):
return [iterable[i // 2] if i % 2 == 0 else element for i in range(2 * len(iterable) - 1)]
Method 15
def intersperse(items, delim):
i = iter(items)
return reduce(lambda x, y: x + [delim, y], i, [i.next()])
Should work for lists or generators.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0