Reputation: 331052
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 #
Upvotes: 35
Views: 96514
Reputation: 20300
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
Upvotes: 1
Reputation: 10117
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
Upvotes: 1
Reputation: 211980
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]
Upvotes: 19
Reputation: 18431
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
Upvotes: 2
Reputation: 28205
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]
.
Upvotes: 2
Reputation: 400284
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.
Upvotes: 61
Reputation: 881695
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
.
Upvotes: 29