tags:

views:

1254

answers:

5

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 #
+7  A: 

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.

Alex Martelli
Judging by the error, I believe he was actually using a list, not a tuple.
Ionuț G. Stan
it probably won't be the best practice to call your dictionary `mylist`.
SilentGhost
Thanks I need linear access to the item, so I will be able to index from 1 to n, so can't use dictionary.
Joan Venge
Sure you can, there are plenty of ways to do that with a dict. i.e. "for k in sorted(mydict.keys()): print mydict[k]"
Carl Meyer
Indexing from 1 to n in the dictionary still works. `for i in range(n): if n in dictionary: print dictionary[n]` does what you want.
S.Lott
+4  A: 

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.

Adam Rosenfield
A: 

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].

inkedmn
+1  A: 

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
jcoon
If he is adding items with increasing indexes, the speed could probably be improved by using an 'if' statement instead of a 'try-catch'. In this case you would be catching the exception every time, which is more "expensive" than checking the length of L every time.
tgray
Do you have a link to source stating it is more "expensive"? Or by how much? That would be helpful.
jcoon
Here's a link to the source of my comment: http://paltman.com/2008/jan/18/try-except-performance-in-python-a-simple-test/
tgray
I added another solution.
jcoon
A: 

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):
      l = len(self)
      if index >= l:
         self.extend(0 for _ in range(l, 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]
Triptych