Populating a list/array by index in Python?

Question:

Is this possible:

myList = []

myList[12] = 'a'
myList[22] = 'b'
myList[32] = 'c'
myList[42] = 'd'

When I try, I get:

# IndexError: list assignment index out of range # 
Asked By: Joan Venge

||

Answers:

For a “sparse list” you could use a dict instead:

mylist = {}
mylist[12] = 'a'

etc. If you want an actual list (initialize it with [], not (), of course!-) you need to fill the un-set slots to _some_thing, e.g. None, by a little auxiliary function or by subclassing list.

Answered By: Alex Martelli

You’ll have to pre-fill it with something (e.g. 0 or None) before you can index it:

myList = [None] * 100  # Create list of 100 'None's
myList[12] = 'a'  # etc.

Alternatively, use a dict instead of a list, as Alex Martelli suggested.

Answered By: Adam Rosenfield

Not without populating the other locations in the list with something (like None or an empty string). Trying to insert an element into a list using the code you wrote would result in an IndexError.

There’s also mylist.insert, but this code:

myList.insert(12,'a')

would just insert ‘a’ at the first unoccupied location in the list (which would be 0 using your example).

So, as I said, there has to be something in the list at indexes 0-11 before you can insert something at myList[12].

Answered By: brettkelly

If you don’t know the size of the list ahead of time, you could use try/except and then Extend the list in the except:

L = []
def add(i, s):
    try:
        L[i] = s
    except IndexError:
        L.extend([None]*(i-len(L)+1))
        L[i] = s

add(12, 'a')
add(22, 'b')

—– Update ———————————————
Per tgray’s comment: If it is likely that your code will throw an Exception most of the time, you should check the length of the List every time, and avoid the Exceptions:

L = []
def add(i, s):
    size = len(L)
    if i >= size:
        L.extend([None]*(i-size+1))
        L[i] = s
Answered By: Jason Coon

Here’s a quick list wrapper that will auto-expand your list with zeros if you attempt to assign a value to a index past it’s length.

class defaultlist(list):

   def __setitem__(self, index, value):
      size = len(self)
      if index >= size:
         self.extend(0 for _ in range(size, index + 1))

      list.__setitem__(self, index, value)

Now you can do this:

>>> a = defaultlist([1,2,3])
>>> a[1] = 5
[1,5,3]
>>> a[5] = 10
[1,5,3,0,0,10]
Answered By: Kenan Banks

Just in case someone needs, I figured out a soluction for my problem, I needed to calc a lot of factorials, some of them could be repeated, so here is my solution:

factorials = {}

def calcFact(v):
    try:
        return factorials[v]
    except KeyError:
        factorials[v] = math.factorial(v)
        return factorials[v]

Testcase:

calcFact(99000)
calcFact(90900)
calcFact(90090)
calcFact(90009)
calcFact(90009) #repeated
calcFact(90009) #repeated

Results:

Repeating mathematical calc: 1.576 s

Using the above code (a list to store repeated values): 1.011 s

Answered By: António Almeida

Building on top of Triptych.. If you want a list of arbitrary dimensions

class dynamiclist(list):
    """ List not needing pre-initialization

    Example:
        l = dynamiclist()
        l[20][1] = 10
        l[21][1] = 20
    """

    def __setitem__(self, index, value):
        size = len(self)
        if index >= size:
            self.extend(dynamiclist() for _ in range(size, index + 1))

        list.__setitem__(self, index, value)

    def __getitem__(self, index):
        size = len(self)
        if index >= size:
            self.extend(dynamiclist() for _ in range(size, index + 1))  # allows dimensions > 1

        return list.__getitem__(self, index)

Example

l = dynamiclist()
l[20][1] = 10
l[21][1] = 20
Answered By: Pithikos
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.