9

I have the following list of strings:

l1 = ['one','two','three']

I want to obtain a list that has, say, these same elements repeated n times. If n=3 I'd get:

l2 = ['one','one','one','two','two','two','three','three','three']

What I am trying is this:

l2 = [3*i for i in l1]

But what I obtain is this:

l2 = ['oneoneone','twotwotwo','threethreethree']

If I try this:

l2 = [3*(str(i)+",") for i in l1]

I obtain:

l2 = ['one,one,one','two,two,two','three,three,three']

What am I missing?

Zizzipupp
  • 1,301
  • 1
  • 11
  • 27
  • 1
    Adding a `','` does not evaluate as separate list elements, it's just a string with a comma character… – deceze Jun 29 '20 at 13:41
  • 1
    If you're doing code golf you could get away with `sorted(l1*3,key=l1.index)` in this example – ScootCork Jun 29 '20 at 14:05

4 Answers4

14
 l2 = [j for i in l1  for j in 3*[i]]

This gives:

 ['one', 'one', 'one', 'two', 'two', 'two', 'three', 'three', 'three']

This is equivalent to:

l2 = []
for i in l1:
    for j in 3*[i]:
       l2.append(j)

Note that 3*[i] creates a list with 3 repeated elements (e.g. ['one', one', 'one'])

Aziz
  • 20,065
  • 8
  • 63
  • 69
5

You can use itertools to transform a list of list into a list (in a fast way) :

from itertools import chain
l1 = ['one','two','third']
l2 = list(chain.from_iterable([[e]*3 for e in l1]))
# l2 = ['one','one','one','two','two','two','three','three','three']

so you can define a function that repeat elements like this :

def repeat_elements(l, n)
    return list(chain.from_iterable([[e]*n for e in l]))
H4kim
  • 418
  • 5
  • 8
5

If you want to use pure list comprehension

 [myList[i//n] for i in range(n*len(myList))]

Explanation:

if original list has k elements, repetition factor is n => total number of items in final list: n*k

To map range n*k to k elements, Divide by n. Remember integer divison

Holy_diver
  • 377
  • 1
  • 15
  • 1
    That's a pretty clever solution. Just a couple of things: use the integer division operator (`//`) rather than the regular division one (`/`). Also, it's redundant to include the zero as the first argument passed to `range()` if you're not passing the three possible arguments at once. Just change it to `range(n*len(myList))` – revliscano Jun 29 '20 at 14:12
  • Thanks @revliscano. I have done the suggested edits – Holy_diver Jun 29 '20 at 14:15
3

You can try to use map with sum

print(list(sum(map(lambda x: [x] * 3, l1), [])))

Output

['one', 'one', 'one', 'two', 'two', 'two', 'three', 'three', 'three']
Leo Arad
  • 4,452
  • 2
  • 6
  • 17