4

This is such a simple issue that I don't know what I'm doing wrong. Basically I want to iterate through the items in an empty list and increase each one according to some criteria. This is an example of what I'm trying to do:

list1 = []
for i in range(5):
    list1[i] = list1[i] + 2*i

This fails with an list index out of range error and I'm stuck. The expected result (what I'm aiming at) would be a list with values:

[0, 2, 4, 6, 8]

Just to be more clear: I'm not after producing that particular list. The question is about how can I modify items of an empty list in a recursive way. As gnibbler showed below, initializing the list was the answer. Cheers.

Gabriel
  • 40,504
  • 73
  • 230
  • 404
  • How about `range(0,9,2)` ? :-) – mgilson Jun 03 '13 at 18:22
  • Obtaining the list is not the issue @mgilson. I want to be able to modify items inside a list in the specified manner. – Gabriel Jun 03 '13 at 18:23
  • That was a simple example, that **particular** list is not my end goal. – Gabriel Jun 03 '13 at 18:23
  • 1
    @Gabriel: If that is the case, please explain what you need to do in more detail so we know how to help you! – Ryan Saxe Jun 03 '13 at 18:29
  • Please be clear about the problem before looking for a solution. – tigeronk2 Jun 03 '13 at 18:34
  • I thought the question was quite clear. I apologize if it was not, I tried to make it as simple as possible but I guess I oversimplified it. – Gabriel Jun 03 '13 at 19:23
  • 1
    You can't iterate over the items of an empty list, because it has no items. It's *empty*. – chepner Jun 03 '13 at 19:58
  • @chepner well, I see that... now. As I say below, I assumed that `python` would treat the initial values of items in an empty list as zeroes by default. I see now that it doesn't and I need to initialize them manually. Cheers. – Gabriel Jun 03 '13 at 23:47

6 Answers6

8

Ruby (for example) lets you assign items beyond the end of the list. Python doesn't - you would have to initialise list1 like this

list1 = [0] * 5
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • I've no idea why this answer got downvoted since this is precisely what I was asking. Thank you @gnibbler. – Gabriel Jun 03 '13 at 18:36
  • I am not a downvoter, but the answer you ask for may not the best one. The list comprehension in Ryan Saxe's answer is the more pythonic way to accomplish your task. Also, understanding the append solution in karthikr's answer would be helpful. I think time will show those answers to be upvoted above the rest. – dansalmo Jun 03 '13 at 19:07
  • 1
    @dansalmo, But it's not what the question was asking for! Of course a list comprehension works for _this example_. It's just not a very good example of the general problem the OP was trying to solve. – John La Rooy Jun 03 '13 at 19:14
  • Spot on @gnibbler. I don't if I simplified the question so much that it became unintelligible, but the fact that such an experienced user as gnibbler got it right on the first try and with a **very** simple answer makes me think people might be jumping to the answering part a bit too quickly. – Gabriel Jun 03 '13 at 19:18
  • I agree with everything, this answer responds the best way for originally initializing a list like this. But for things extremely complicated, numpy.vectorize would be very useful for these kinds of things as I mentioned in my answer. But yes, this does answer the question in the most easy to understand and concise way. +1 – Ryan Saxe Jun 03 '13 at 19:48
6

So when doing this you are actually using i so you can just do your math to i and just set it to do that. there is no need to try and do the math to what is going to be in the list when you already have i. So just do list comprehension:

list1 = [2*i for i in range(5)]

Since you say that it is more complex, just don't use list comprehension, edit your for loop as such:

for i in range(5):
    x = 2*i
    list1[i] = x

This way you can keep doing things until you finally have the outcome you want, store it in a variable, and set it accordingly! You could also do list1.append(x), which I actually prefer because it will work with any list even if it's not in order like a list made with range

Edit: Since you want to be able to manipulate the array like you do, I would suggest using numpy! There is this great thing called vectorize so you can actually apply a function to a 1D array:

import numpy as np
list1 = range(5)
def my_func(x):
    y = x * 2
vfunc = np.vectorize(my_func)
vfunc(list1)
>>> array([0, 2, 4, 6, 8])

I would advise only using this for more complex functions, because you can use numpy broadcasting for easy things like multiplying by two.

Ryan Saxe
  • 17,123
  • 23
  • 80
  • 128
3

Your list is empty, so when you try to read an element of the list (right hand side of this line)

list1[i] = list1[i] + 2*i

it doesn't exist, so you get the error message.

Marichyasana
  • 2,966
  • 1
  • 19
  • 20
1

You may also wish to consider using numpy. The multiplication operation is overloaded to be performed on each element of the array. Depending on the size of your list and the operations you plan to perform on it, using numpy very well may be the most efficient approach.

Example:

>>> import numpy
>>> 2 * numpy.arange(5)
array([0, 2, 4, 6, 8])
David Cain
  • 16,484
  • 14
  • 65
  • 75
0

I would instead write

for i in range(5):
    list1.append(2*i)
Chris.Stover
  • 516
  • 6
  • 14
  • That only generates that particular list which is not my goal. I want to be able to manipulate items in an empty list through an iterative process. – Gabriel Jun 03 '13 at 19:15
0

Yet another way to do this is to use the append method on your list. The reason you're getting an out of range error is because you're saying:

list1 = []
list1.__getitem__(0) 

and then manipulate this item, BUT that item does not exist since your made an empty list.

Proof of concept:

list1 = []
list1[1]
IndexError: list index out of range

We can, however, append new stuff to this list like so:

list1 = []
for i in range(5):
    list1.append(i * 2)
SgtMajorJay
  • 129
  • 4