I am trying to solve a seemingly simple problem on Python. I am trying to update the last 3 element of a list to other integers. Here is the code:
list = [0,1,2,3,4]
for i in xrange(len(list[2:])):
list[2:][i] = 44444
print list
But when I print the list, it still remains the same. I observe the changes in debugger and I found that the list doesn't update in the loop. I tried searching elsewhere on Google and Stack Overflow, but none of them provide answers to this simple problem.
Let me know what you guys think about this. Thanks.
A slice of a list is a new list; it doesn’t reference the original or anything like that. Assign to list[2 + i] instead. (You can avoid making an extra slice to get the length in the same way.)
list = [0, 1, 2, 3, 4]
for i in xrange(len(list) - 2):
list[2 + i] = 44444
print list
A slice creates a new list, unless you assign to it:
>>> values = [0, 1, 2, 3, 4]
>>> values[-3:] = [4444] * 3
>>> values
[0, 1, 4444, 4444, 4444]
By using for i in xrange(len(list[2:])): you are reducing the length of list from 5 to 3. Your loop would iterate only for the first 3 list items.
Instead you could do something like this:
a=[0,1,2,3,4,5]
for i in range(3,len(a)):
a[i]=444
print(a)
Related
I am relatively new to python and I am still trying to learn the basics of the language. I stumbled upon a question which asks you to rearrange the list by modifying the original. What you are supposed to do is move all the even index values to the front (in reverse order) followed by the odd index values.
Example:
l = [0, 1, 2, 3, 4, 5, 6]
l = [6, 4, 2, 0, 1, 3, 5]
My initial approach was to just use the following:
l = l[::-2] + l[1::2]
However, apparently this is considered 'creating a new list' rather than looping through the original list to modify it.
As such, I was hoping to get some ideas or hints as to how I should approach this particular question. I know that I can use a for loop or a while loop to cycle through the elements / index, but I don't know how to do a swap or anything else for that matter.
You can do it by assigning to a list slice instead of a variable:
l[:] = l[::2][::-1] + l[1::2]
Your expression for the reversed even elements was also wrong. Use l[::2] to get all the even numbers, then reverse that with [::-1].
This is effectively equivalent to:
templ = l[::2][::-1] + l[1::2]
for i in range(len(l)):
l[i] = templ[i]
The for loop modifies the original list in place.
In my program I have many lines where I need to both iterate over a something and modify it in that same for loop.
However, I know that modifying the thing over which you're iterating is bad because it may - probably will - result in an undesired result.
So I've been doing something like this:
for el_idx, el in enumerate(theList):
if theList[el_idx].IsSomething() is True:
theList[el_idx].SetIt(False)
Is this the best way to do this?
This is a conceptual misunderstanding.
It is dangerous to modify the list itself from within the iteration, because of the way Python translates the loop to lower level code. This can cause unexpected side effects during the iteration, there's a good example here :
https://unspecified.wordpress.com/2009/02/12/thou-shalt-not-modify-a-list-during-iteration/
But modifying mutable objects stored in the list is acceptable, and common practice.
I suspect that you're thinking that because the list is made up of those objects, that modifying those objects modifies the list. This is understandable - it's just not how it's normally thought of. If it helps, consider that the list only really contains references to those objects. When you modify the objects within the loop - you are merely using the list to modify the objects, not modifying the list itself.
What you should not do is add or remove items from the list during the iteration.
Your problem seems to be unclear to me. But if we talk about harmful of modifying list during a for loop iteration in Python. I can think about two scenarios.
First, You modify some elements in list that suppose to be used on the next round of computation as its original value.
e.g. You want to write a program that have such inputs and outputs like these.
Input:
[1, 2, 3, 4]
Expected output:
[1, 3, 6, 10] #[1, 1 + 2, 1 + 2 + 3, 1 + 2 + 3 + 4]
But...you write a code in this way:
#!/usr/bin/env python
mylist = [1, 2, 3, 4]
for idx, n in enumerate(mylist):
mylist[idx] = sum(mylist[:idx + 1])
print mylist
Result is:
[1, 3, 7, 15] # undesired result
Second, you make some change on size of list during a for loop iteration.
e.g. From python-delete-all-entries-of-a-value-in-list:
>>> s=[1,4,1,4,1,4,1,1,0,1]
>>> for i in s:
... if i ==1: s.remove(i)
...
>>> s
[4, 4, 4, 0, 1]
The example shows the undesired result that raised from side-effect of changing size in list. This obviously shows you that for each loop in Python can not handle list with dynamic size in a proper way. Below, I show you some simple way to overcome this problem:
#!/usr/bin/env python
s=[1, 4, 1, 4, 1, 4, 1, 1, 0, 1]
list_size=len(s)
i=0
while i!=list_size:
if s[i]==1:
del s[i]
list_size=len(s)
else:
i=i + 1
print s
Result:
[4, 4, 4, 0]
Conclusion: It's definitely not harmful to modify any elements in list during a loop iteration, if you don't 1) make change on size of list 2) make some side-effect of computation by your own.
you could get index first
idx = [ el_idx for el_idx, el in enumerate(theList) if el.IsSomething() ]
[ theList[i].SetIt(False) for i in idx ]
Let's say I have an array
a = np.array[5, 3, 2]
and based on that array I want to return a new array in the form:
b = np.array[ [0, 1, 2, 3, 4], [0, 1, 2], [0, 1] ]
I've been trying:
for item in a:
b = np.hstack(np.arange(item))
print b
but this only gives me the elements without joining them into an array;
for item in a:
b = b.append((b[:], b[item]))
print b
but this approach blows up nicely with a:
AttributeError: 'numpy.ndarray' object has no attribute 'append'
I have tried other things, like:
b[item] = np.arange(item),
but that one complains about out-of-bounds indices.
And
b = np.zeros(len(a))
for item in np.arange(len(a)):
b[item] = np.arange(b[item])
print b
which complains with
ValueError: setting an array element with a sequence.
That last one is the one that looks more promising and, searching for some questions on this site (https://stackoverflow.com/a/13311979/531687) I know that the problem is that I am trying to fit a sequence where a value is expected, but I can't figure out my way around it.
How can I go about this?
This should work
b = [range(x) for x in a]
update
The brackets [...] here create a list and inside an iterator can be used to define the items in the list. In this case the items of of type range(x) for each item in a.
Note that there is a difference in implementation between python2 and python3 here. In python2 this actually generates a list of lists. In python3 however this generates a lists of generators (the python2 equivalent would be xrange), which is typically more efficient.
This question already has answers here:
Why does this iterative list-growing code give IndexError: list assignment index out of range? How can I repeatedly add (append) elements to a list?
(9 answers)
Closed 4 months ago.
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.
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
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.
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.
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])
I would instead write
for i in range(5):
list1.append(2*i)
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)
I was instructed to prevent this from happening in a Python program but frankly I have no idea how this is even possible. Can someone give an example of how you can slice a list and insert something into it to make it bigger? Thanks
>>> a = [1,2,3]
>>> a[:0] = [4]
>>> a
[4, 1, 2, 3]
a[:0] is the "slice of list a beginning before any elements and ending before index 0", which is initially an empty slice (since there are no elements in the original list before index 0). If you set it to be a non-empty list, that will expand the original list with those elements. You could also do the same anywhere else in the list by specifying a zero-width slice (or a non-zero width slice, if you want to also replace existing elements):
>>> a[1:1] = [6,7]
>>> a
[4, 6, 7, 1, 2, 3]
To prevent this from happening you can subclass the builtin list and then over-ride these methods for details refer here