3

Suppose I have list

l = ['a', 'c', 'b']

and what I want is a list where those elements appear twice, one after the other, so

['a', 'a', 'c', 'c', 'b', 'b']

and I want to do this in the most pythonic way possible.

My half solution is doing something like

[[l[i], l[i]] for i in range(len(l))]

which yields

[['a', 'a'], ['c', 'c'], ['b', 'b']]

From here, I'd have to parse (walk) the list to remove the inner lists and obtain a single flat list.

Anyone has a better idea to do this in one go? Obviously things like l * 2 wouldn't help as it gives ['a', 'c', 'b', 'a', 'c', 'b'] and I want the same elements adjacent.

mar tin
  • 9,266
  • 23
  • 72
  • 97

7 Answers7

5
l_2 = [item for item in l for i in range(n)]

Link to origin: Stackoverflow: Repeating elements of a list n times

Community
  • 1
  • 1
UpSampler
  • 399
  • 2
  • 6
  • Choosing this as it seems the more elegant one. Note that timing the execution of this gives `1000000 loops, best of 3: 1.49 µs per loop` as compared to @Yousaf 's answer which gives `The slowest run took 5.32 times longer than the fastest. This could mean that an intermediate result is being cached. 1000000 loops, best of 3: 1.12 µs per loop` – mar tin Jan 20 '17 at 12:19
  • 1
    I reckon to use a longer list for timing. Three elements are so short that the time does not really matter. I also got 'The slowest run took 5.41 times longer than the fastest' for the code above. – UpSampler Jan 20 '17 at 12:26
4

Using only list comprehension, you can do:

[i for j in my_list for i in [j]*2]

Output:

>>> my_list = ['a', 'c', 'b']
>>> [i for j in my_list for i in [j]*2]
['a', 'a', 'c', 'c', 'b', 'b']
ettanany
  • 19,038
  • 9
  • 47
  • 63
3

You can zip the list against itself, then flatten it in a list comprehension.

>>> [i for j in zip(l,l) for i in j]
['a', 'a', 'c', 'c', 'b', 'b']
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
2

You can use zip function

l = ['a', 'c', 'b']
a = [i for j in zip(l,l) for i in j]
print(a)

Output

['a', 'a', 'c', 'c', 'b', 'b']
Yousaf
  • 27,861
  • 6
  • 44
  • 69
1

More general:

def ntimes(iterable, times=2):
    for elt in iterable:
        for _ in range(times):
            yield elt
Katriel
  • 120,462
  • 19
  • 136
  • 170
1

Here is a short solution without list comprehension, using the intuitive idea l*2:

sorted(l*2, key=l.index)
#['a', 'a', 'c', 'c', 'b', 'b']
Colonel Beauvel
  • 30,423
  • 11
  • 47
  • 87
1

If you like functional approaches, you can do this:

from itertools import chain, tee

l = ['a', 'c', 'b']
n = 2

list(chain.from_iterable(zip(*tee(l, n))))

While this might not perform as fast as the other answers, it can easily be used for arbitrary iterables (especially when they are infite or when you don't know when they end) by omitting list().

(Note that some of the other answers can also be adapted for arbitrary iterables by replacing their list comprehension by a generator expression.)

blubberdiblub
  • 4,085
  • 1
  • 28
  • 30