Create list of single item repeated N times
Asked Answered
M

10

786

I want to create a series of lists, all of varying lengths. Each list will contain the same element e, repeated n times (where n = length of the list).

How do I create the lists, without using a list comprehension [e for number in range(n)] for each list?

Micropyle answered 11/8, 2010 at 14:1 Comment(0)
M
1155

You can also write:

[e] * n

You should note that if e is for example an empty list you get a list with n references to the same list, not n independent empty lists.

Performance testing

At first glance it seems that repeat is the fastest way to create a list with n identical elements:

>>> timeit.timeit('itertools.repeat(0, 10)', 'import itertools', number = 1000000)
0.37095273281943264
>>> timeit.timeit('[0] * 10', 'import itertools', number = 1000000)
0.5577236771712819

But wait - it's not a fair test...

>>> itertools.repeat(0, 10)
repeat(0, 10)  # Not a list!!!

The function itertools.repeat doesn't actually create the list, it just creates an object that can be used to create a list if you wish! Let's try that again, but converting to a list:

>>> timeit.timeit('list(itertools.repeat(0, 10))', 'import itertools', number = 1000000)
1.7508119747063233

So if you want a list, use [e] * n. If you want to generate the elements lazily, use repeat.

Myronmyrrh answered 11/8, 2010 at 14:4 Comment(2)
It's highly unlikely that the performance of creating a list with identical elements will be a critical component of the performance of a python program.Horsehair
As mentioned above, if e is an empty list [[]] * n can produce unexpected results . To create unique empty sub-lists, use for-comprehension: [[] for i in range(0,n)]Gastight
P
219
>>> [5] * 4
[5, 5, 5, 5]

Be careful when the item being repeated is a list. The list will not be cloned: all the elements will refer to the same list!

>>> x=[5]
>>> y=[x] * 4
>>> y
[[5], [5], [5], [5]]
>>> y[0][0] = 6
>>> y
[[6], [6], [6], [6]]
Pain answered 11/8, 2010 at 14:5 Comment(2)
Does it make sense? Creating a list, then changing one elem, and the whole list gets changed?Dummy
@Timo. Yes. The outer list stores four references to the same inner list.Kaleidoscope
C
127

Create List of Single Item Repeated n Times in Python

Depending on your use-case, you want to use different techniques with different semantics.

Multiply a list for Immutable items

For immutable items, like None, bools, ints, floats, strings, tuples, or frozensets, you can do it like this:

[e] * 4

For example:

>>> [None] * 4
[None, None, None, None]

Note that this is usually only used with immutable items (strings, tuples, frozensets, etc) in the list, because they all point to the same item in the same place in memory.

For an example use-case, I use this when I have to build a table with a schema of all strings, so that I don't have to give a highly redundant one to one mapping.

schema = ['string'] * len(columns)

Multiply the list where we want the same item with mutable state repeated

Multiplying a list gives us the same elements over and over. The need for this is infrequent:

[iter(iterable)] * 4

This is sometimes used to map an iterable into a list of lists:

>>> iterable = range(12)
>>> a_list = [iter(iterable)] * 4
>>> [[next(l) for l in a_list] for i in range(3)] # uninteresting usage
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]

We can see that a_list contains the same range iterator four times:

>>> from pprint import pprint
>>> pprint(a_list)
[<range_iterator object at 0x7f9fe3b58420>,
 <range_iterator object at 0x7f9fe3b58420>,
 <range_iterator object at 0x7f9fe3b58420>,
 <range_iterator object at 0x7f9fe3b58420>]

Mutable items

I've used Python for a long time now, and I have seen very few use-cases where I would do the above with mutable objects.

Instead, to have repeated, say, a mutable empty list, set, or dict, you should do something like this:

list_of_lists = [[] for _ in iterator_of_needed_length]

The underscore is simply a throwaway variable name in this context.

If you only have the number, that would be:

list_of_lists = [[] for _ in range(4)]

The _ as the throwaway name is not really special, but a static code analyzer will probably complain if you don't intend to use the variable and use any other name.


Caveats for using the multiplication method with mutable items:

Beware doing this with mutable objects, when you change one of them, they all change because they're all the same object:

foo = [[]] * 4
foo[0].append('x')

foo now returns:

[['x'], ['x'], ['x'], ['x']]

But with immutable objects, you can make it work because you change the reference, not the object:

>>> l = [0] * 4
>>> l[0] += 1
>>> l
[1, 0, 0, 0]

>>> l = [frozenset()] * 4
>>> l[0] |= set('abc')
>>> l
[frozenset(['a', 'c', 'b']), frozenset([]), frozenset([]), frozenset([])]

But again, mutable objects are no good for this, because in-place operations change the object, not the reference:

l = [set()] * 4
>>> l[0] |= set('abc')    
>>> l
[set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b'])]
Container answered 3/7, 2014 at 15:18 Comment(3)
The "Multiply the list where we want the same item repeated" section doesn't appear related to the question. It looks like an answer to How do I split a list into equally-sized chunks? instead.Hydrophane
It illustrates one of the use cases for the question of how to, "Create list of single item repeated n times." - in general, sometimes an answer may be applicable to more than one question.Container
Ah, I see, you're just trying to motivate why the aliasing might sometimes be deliberate/beneficial.Hydrophane
M
32

Itertools has a function just for that:

import itertools
it = itertools.repeat(e,n)

Of course itertools gives you a iterator instead of a list. [e] * n gives you a list, but, depending on what you will do with those sequences, the itertools variant can be much more efficient.

Milanmilanese answered 11/8, 2010 at 14:2 Comment(0)
H
18

As others have pointed out, using the * operator for a mutable object duplicates references, so if you change one you change them all. If you want to create independent instances of a mutable object, your xrange syntax is the most Pythonic way to do this. If you are bothered by having a named variable that is never used, you can use the anonymous underscore variable.

[e for _ in xrange(n)]
Hallah answered 27/1, 2015 at 17:53 Comment(1)
Should be range() instead xrange(). Example: my_list``` = [1 for _ in range(10)]; and my_list will be [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]Anatolia
F
13
[e] * n

should work

Festa answered 11/8, 2010 at 14:6 Comment(0)
M
9

If you are looking for a simple repeat like:

[1, 2, 3, 1, 2, 3, 1, 2, 3]

simply use:

[1, 2, 3] * 3

But if you are seeking for:

[1, 1, 1, 2, 2, 2, 3, 3, 3]

This one is better while takes more time:

numpy.concatenate([([i]*3) for i in [1,2,3]], axis=0)
Marconigraph answered 8/3, 2021 at 9:15 Comment(0)
N
4

Sorry for my really late answer You can use numpy.repeat easily. Just by writing the value that you would like to produce and the number of repetition.

import numpy as np
x = [1,2,3]
y = np.linspace(0,1000,10000)
for i in x:
    new_x = np.repeat(i,len(y))
    print(new_x)
Nodal answered 27/7, 2021 at 10:27 Comment(2)
If you are already using Numpy for other reasons, this one is good to know (but trivial enough to be obvious to those who need it). For solving the problem from scratch, adding a huge third-party library just for this is silly at best and irresponsible at worst.Alboran
what's less obvious is the massive speedup that you get. I would have imagined python to optimise these types of operations somehow, but no! (see the answer after my revision has been added).Exemption
T
3

If you're seeking

[1, 1, 1, 2, 2, 2, 3, 3, 3]

without numpy, you can use the builtin itertools module

from itertools import chain
list(chain.from_iterable(zip(*[[1,2,3]]*3)))

With a simple list comprehension (without even itertools)

[e for x in zip(*[[1,2,3]]*3) for e in x]
Toilet answered 28/5, 2022 at 8:20 Comment(0)
F
-1
import numpy as np
a = np.full(fill_value=1, shape=3)
print(a)
b = np.repeat(a=[1,2,3],repeats=3)
print(b)
c = np.repeat(a=[[1,2,3]],repeats=3,axis=0).flatten()
print(c)
Feast answered 8/6, 2023 at 13:49 Comment(2)
Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, can you edit your answer to include an explanation of what you're doing and why you believe it is the best approach?Afterward
That's even more important here, given how many answers have already been received. How does your approach differ from the other answers given? Why do you prefer this approach? Is it better suited for particular situations than other answers?Afterward

© 2022 - 2024 — McMap. All rights reserved.