How remove() function was executed in python? - python

Actually I was working with this code:
m=[0,1,2,3,4,5,6,7]
for i in m:
m.remove(i)
print(m)
This looks pretty simple.
for i in m:
print(i)
will print every elements in the list m. So the for part in our code will extract every elements of the list and remove it one by one. So the output that I except is [].
But I got [1,3,5,7].
How it can be the output and where I was wrong?

when you use (for i in m), i starts from index zero so i is the element of index 0 which its value is 0 then in for loop you'll delete zero value.
now your list is [1,2,3,4,5,6,7] and i is the element of index 1 which its value is 2.
after deleting 2 your list would be like [2,3,4,5,6,7], now i is the element of index 2 which its value is 4 and ....
here is how this for loop works and why the output is like that.
to remove all element in a list you can use:
for i in range(len(m)):
m.remove(m[0])
or
m.clear()

If you know how to use a debugger, that would be the ideal way to diagnose this, otherwise, try running this code to see what's going on:
x = [0, 1, 2, 3, 4, 5, 6, 7]
for i in x.copy():
x.remove(i)
print(x)
print(x)
m = [0, 1, 2, 3, 4, 5, 6, 7]
for i in m:
m.remove(i)
print(m)
print(m)
During a given execution, the for loop accesses an element and then deletes it. For example, it first deletes the element at index 0, with value 0, leaving you with [1, 2, 3, 4, 5, 6, 7]. Then it moves on to the element at index 1, value 2, and deletes that, leaving you with [1, 3, 4, 5, 6, 7].
In general, avoid messing around with a list in Python. If you have to delete all elements, use m.clear(). If you have to delete some elements or do some other stuff, prefer to use list comprehension to create a new object.

What happens here is, you're removing items in the list on the go.
Eg,
On the first remove() call, it removes 0 from the list (current
index is 0).
On the second remove() call, the current index is 1,
but the list contains [1,2,3,...]. Now the the index 1 contains "2"
instead of "1". Because 0 has been removed and the size of list is
just changed.
So to clear list in python, you can use,
m.clear()

i don`t know why it is not remove each item, but i worked on it and it works like this:
m=[0,1,2,3,4,5,6,7]
while m != []:
[m.remove(i) for i in m]
print(m)

Related

Python Slicing Issue: every other element in list, starting with last element not working?

so I have a list of numbers, and I want to start at the last element of the list and print every other element.
So given list = [1, 2, 3, 4, 5, 6] I would print 6, 4 and 2. My issue is that slicing is not printing the last element.
list = [1, 2, 3, 4, 5, 6]
for i in list[-1::-2]:
print(list[i])
this merely prints 4 and 2, showing me that the last digit is not included. I have also tried omitting the -1 and just using list[::-2]. It takes every odd digit (4 and 2) but does not include 6. I want to use slicing to achieve this result, but clearly I am misunderstanding how to use it. Any help much appreciated (this is my first stackOverflow question btw!)
Please avoid using the variable names as a list.
ls = [1, 2, 3, 4, 5, 6]
for i in ls[-1::-2]:
print(i)
You're iterating all the elements of the list using the in method. It doesn't provide you an index that you will use to print.
When you're trying to print list[i] it will raise an error because when i=6 then list[i] element don't exist in the list.
You can simply do slicing by using:
ls = [1, 2, 3, 4, 5, 6]
print(ls[-1::-2])
and don't use the list as a variable name because it is a keyword in Python so you will get an error.
Have you tried printing just i instead of the list[i]?
You should remember here that if you iterate through a reversed list, you need not do indexing again. The i would hold the value of the list element.
Please try:
for i in ls[::-2]:
print(i)

Trying to add a new last element in a list while using the method insert()

thanks for reading.
I'm currently learning python, yet a silly question popped in my head.
I was writting some lines of code usinng the things I've learnt and I noticed something that doesn't make "sense" (whatever that means) to me.
Here is my code:
//printing the last element of my list
numbers = [5, 4 ,3 ,2 ,1]
print(numbers[-1])
//changing values in my list
numbers[0] = 1
numbers[-1] = 1
//inserting values on my list
print(numbers)
numbers.insert(0,"Hello")
**numbers.insert(-1, "Hello")**
print(numbers)
the question pops with the line I marked as ****BOLD****: Why I can't modify the last element of my list when I put -1?, I touhght that when you call the element [-1] in a list it shows the last element, why this doesn't work when I'm using the insert () method and calling -1?
this is what happens when you run all the code.
1
[1, 4, 3, 2, 1]
['Hello', 1, 4, 3, 2, 'Hello', 1]
When you use insert, you are inserting at the specified index position. Remember that lst[-x] is the same as lst[len(lst)-1-x]. For example, lst[-1] and lst[len(lst)-1-1] both refer to the last index position in the list. Once you know this, the behavior you are seeing with the negative index positions starts to make more sense:
nums = [1, 2, 3, 4, 5]
nums.insert(1, 'Hello') # Insert at index position 1.
# Result: [1, 'Hello', 2, 3, 4, 5]
nums.insert(-1, 'Bye') # Insert at index position len(nums)-1-1 = 4.
# Same as: nums.insert(4, 'Bye')
# Result: [1, 'Hello', 2, 3, 4, 'Bye', 5]
nums.insert(-2, 'Good') # Insert at index position len(nums)-1-2 = 5.
# Same as: nums.insert(5, 'Good')
# Result: [1, 'Hello', 2, 3, 4, 'Good', 'Bye', 5]
To insert at the end of the list using insert:
nums = [1, 2, 3]
nums.insert(len(nums), 'Hello')
# Result: [1, 2, 3, 'Hello']
As you can see, 'Hello' was inserted in index position 3 (the original len(nums)) as specified.
If all you want to do is add an element at the end of a list, you could use append instead:
nums = [1, 2, 3]
nums.append('Hello')
# Result: [1, 2, 3, 'Hello']
To insert at the end of a list, you have to use
numbers.insert(len(numbers), 'Hello')
This will output
[5, 4, 3, 2, 1, 'Hello']
The problem you faced occurs because numbers[-i] is equivalent to numbers[len(numbers) - 1 - i]. So, numbers[-1] is actually numbers[5 - 1 - 1], i.e., numbers[3], which is exactly what was happening in your program. Insertion was happening at the 3rd index.
Why I can't modify the last element of my list when I put -1?, I touhght that when you call the element [-1] in a list it shows the last element, why this doesn't work when I'm using the insert () method and calling -1?
Because -1 is len(x)-1, it's the position of the last item but it "points to" right before the last item0, in the same way 0 points right before the first item. Basically:
[a][b][c][d][e]
0 1 2 3 4 5
-5 -4 -3 -2 -1
Thus in the same way insert(0, ...) inserts before the first item, insert(-1, ...) inserts right before the last item.
To add an element at the end, you need to insert right after the last item.
[0] that's the "pointer" view of indexing, shared by most 0-indexed languages: the index is seen as an offset from the array pointer.

Writing Python code that works like the reverse() function

I'm looking to break down the reverse() function and write it out in code for practice. I eventually figured out how to do it (step thru the original list backwards and append to the new 'reversed' list) but wondering why this doesn't work.
def reverse(list):
newlist = []
index = 0
while index < len(list):
newlist[index] = list[(len(list)) - 1 - index]
index = index + 1
return newlist
list = [1, 2, 3, 4, 5]
print(reverse(list))
In Python, you cannot access/update an element of a list, if the index is not in the range of 0 and length of the list - 1.
In your case, you are trying to assign to element at 0, but the list is empty. So, it doesn't have index 0. That is why it fails with the error,
IndexError: list assignment index out of range
Instead, you can use append function, like this
newlist.append(list[(len(list)) - 1 - index])
Apart from that, you can use range function to count backwards like this
for index in range(len(list) - 1, -1, -1):
newlist.append(list[index])
you don't even have to increment the index yourself, for loop takes care of it.
As suggested by #abarnert, you can actually iterate the list and add the elements at the beginning every time, like this
>>> def reverse(mylist):
... result = []
... for item in mylist:
... result.insert(0, item)
... return result
...
>>> reverse([1, 2, 3, 4, 5])
[5, 4, 3, 2, 1]
If you want to create a new reversed list, you may not have to write a function on your own, instead you can use the slicing notation to create a new reversed list, like this
>>> mylist = [1, 2, 3, 4, 5]
>>> mylist[::-1]
[5, 4, 3, 2, 1]
but this doesn't change the original object.
>>> mylist = [1, 2, 3, 4, 5]
>>> mylist[::-1]
[5, 4, 3, 2, 1]
>>> mylist
[1, 2, 3, 4, 5]
if you want to change the original object, just assign the slice back to the slice of the original object, like this
>>> mylist
[1, 2, 3, 4, 5]
>>> mylist[:] = mylist[::-1]
>>> mylist
[5, 4, 3, 2, 1]
Note: reversed actually returns a reverse iterator object, not a list. So, it doesn't build the entire list reversed. Instead it returns elements one by one when iterated with next protocol.
>>> reversed([1, 2, 3, 4, 5])
<list_reverseiterator object at 0x7fdc118ba978>
>>> for item in reversed([1, 2, 3, 4, 5]):
... print(item)
...
...
5
4
3
2
1
So, you might want to make it a generator function, like this
>>> def reverse(mylist):
... for index in range(len(mylist) - 1, -1, -1):
... yield mylist[index]
...
...
>>> reverse([1, 2, 3, 4, 5])
<generator object reverse at 0x7fdc118f99d8>
So the reverse function returns a generator object. If you want a list, then you can create one with list function, like this
>>> list(reverse([1, 2, 3, 4, 5]))
[5, 4, 3, 2, 1]
if you are just going to process it one by one, then iterate it with a for loop, like this
>>> for i in reverse([1, 2, 3, 4, 5]):
... print(i)
...
...
5
4
3
2
1
First off don't override build-ins (list in your case) second newlist has a len of 0 therefore cannot be accessed by index.
def reverse(mylist):
newlist = [0] * len(mylist)
index = 0
while index < len(mylist):
newlist[index] = mylist[(len(mylist)) - 1 - index]
index = index + 1
return newlist
mylist = [1, 2, 3, 4, 5]
print(reverse(mylist))
you can create a list with values of the same lenght as your input list like so
newlist = [0] * len(mylist)
You need to use list.append. newlist[0] is a valid operation, if the list has atleast one element in it, but newlist is empty in this very first iteration. Also, list is not a good name for a variable, as there is a python builtin container with the same name:
def reverse(lst):
newlist = []
index = 0
while index < len(lst):
newlist.append(lst[(len(list)) - 1 - index])
index += 1
return newlist
list = [1, 2, 3, 4, 5]
print(reverse(list))
You can't assign to an arbitrary index for a 0-length list. Doing so raises an IndexError. Since you're assigning the elements in order, you can just do an append instead of an assignment to an index:
newlist.append(l[(len(l)) - 1 - index])
Append modifies the list and increases its length automatically.
Another way to get your original code to work would be to change the initialization of newlist so that it has sufficient length to support your index operations:
newlist = [None for _ in range(len(l))]
I would also like to note that it's not a good idea to name things after built-in types and functions. Doing so shadows the functionality of the built-ins.
To write the function you're trying to write, see thefourtheye's answer.
But that isn't how reverse works, or what it does. Instead of creating a new list, it modifies the existing list in-place.
If you think about it, that's pretty easy: just go through half the indices, for each index N, swap the Nth from the left and the Nth from the right.*
So, sticking with your existing framework:
def reverse(lst):
index = 0
while index < len(lst)/2:
lst[index], lst[len(lst) - 1 - index] = lst[len(lst) - 1 - index], lst[index]
index = index + 1
As a side note, using while loops like this is almost always a bad idea. If you want to loop over a range of numbers, just use for index in range(len(lst)):. Besides reducing three lines of code to one and making it more obvious what you're doing, it removes multiple places where you could make a simple but painful-to-debug mistake.
Also, note that in most cases, in Python, it's easier to use a negative index to mean "from the right edge" than to do the math yourself, and again it will usually remove a possible place you could easily make a painful mistake. But in this particular case, it might not actually be any less error-prone…
* You do have to make sure you think through the edge cases. It doesn't matter whether for odd lists you swap the middle element with itself or not, but just make sure you don't round the wrong way and go one element too far or too short. Which is a great opportunity to learn about how to write good unit tests…
probably check this out:
def reverse(lst):
newList = []
countList = len(lst) - 1
for x in range(countList,-1,-1):
newList.append(lst[x])
return newList
def main():
lst = [9,8,7,6,5,4,2]
print(reverse(lst))
main()

Find and remove least common element in array (Python)

I am trying to find the least common element in an array of integers and remove it, and return the list in the same order.
This is what I have done, but when the list is [1, 2, 3, 4, 5], my function should return [], but returns [2, 4] instead.
def check(data):
for i in data:
if data.count(i) <= 1:
data.remove(i)
return data
data = [1, 2, 3, 4, 5]
print check(data)
Deleting items from a list you are iterating over causes you to skip items (ie the next item following each one you delete).
Instead, make a new list containing only the values you want to keep.
from collections import Counter
def check(data):
ctr = Counter(data)
least = min(ctr.values())
return [d for d in data if ctr[d] > least]
You shouldn't modify (especially delete) elements from a list while you are iterating over it.
What happened is:
Initially the iterator is at the 1st element, i.e. i = 1
Since d.count(1) is 1, so you delete 1 from the list.
The list is now [2,3,4,5], but the iterator advances to the 2nd element which is now the 3.
Since d.count(3) is 1 you delete it making the list [2,4,5]
The iterator advances to the 3rd element which is now 5.
Again you delete the 5 making the list [2,4].
Your algorithm should:
Get a count of all elements
Find the smallest count.
Find the elements with the smallest count.
Remove the elements found in step 3 from the list.
You shouldn't check data.count(i) <= 1. What happens in this case: [1, 1, 2, 2, 3, 3, 3]? 1 and 2 are the least common elements but you will never delete them. Likewise it is a bad idea to mutate a list in a for loop.
One thing you can do is use the Counter class.
Take an appropriate slice of the tail of the most_common() method (they entries get less frequent as you go down the list, so this is why you take the tail as opposed to the head).
Then you can repeatedly search the list for these occurrences and remove them until their are no occurrences left.
one another try:
def check(data):
ctr = Counter(data)
keys = ctr.keys()
vals = ctr.values()
least = []
m = min(vals)
for i in range(0,len(vals)):
if vals[i] == m:
least.append(keys[i])
print least
data = [1, 2, 3, 4, 5,1]
result = check(data)

Confusing behavior of Python for statement

I have the following python code:
x = range(0,10)
print x
for number in x:
print(number)
if number%2<> 0:
x.remove(number)
print x
Oddly, the out put is this:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
0
1
3
5
7
9
[0, 2, 4, 6, 8]
The first and last lines are right, but why are 2,4,6, and 8 not printed out? The print statement is not inside the if statement!
I'm using python(x,y) on windows 7. Also, I'm new to Python...I'm used to C++
You're removing items from the list (x.remove) while iterating over it (for number in x).
for-in maintains an index separately, and that is why modifying the list gives unexpected behavior.
The list is iterated using its index, but when you remove elements you skip some indices.
E.g:
[0,1,2,...] # (iterator is at second - print 1)
remove
[0,2,3,...] # (iterator is still at second)
iterator advances
[0,2,3,...] # (iterator is at third - print 3)
Add some print statements for clarity:
x = range(10)
for index, number in enumerate(x):
print "x is ", x
print "element is", number
print "index is ", index
print
if number % 2 == 0:
x.remove(number)
And the output:
x is [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
element is 0
index is 0
x is [1, 2, 3, 4, 5, 6, 7, 8, 9]
element is 2
index is 1
x is [1, 3, 4, 5, 6, 7, 8, 9]
element is 4
index is 2
x is [1, 3, 5, 6, 7, 8, 9]
element is 6
index is 3
x is [1, 3, 5, 7, 8, 9]
element is 8
index is 4
As you can see, index keeps going up by 1, even though you remove elements from the list. This is what causes the loop to skip elements.
As others have pointed out, looping over a list and removing elements from it isn't a good idea. Loop over a copy instead:
for number in x[:]:
Or:
for number in list(x):
Better yet, make a new list with a list comprehension:
[number for number in x if number % 2 == 0]
Basically you can have weird behavior when you iterate something while removing at the same time. What's happening is that you're skipping some values due to them being shifted to indexes that you already iterated over.
A better way of doing what you want (filter out some items), would be to use a list comprehension, for instance:
[x for x in range(10) if x%2==0]
You could simply use the range step to only create even numbers, but the above solution let's you filter out on any condition.
The reason why some numbers aren't printed is that the values are changing positions while you loop and remove them. When you remove the 1, you can imagine all the values being shifted by one position, the iterator is pointing to where the 2 used to be, but now the value there is 3, so the 2 is never printed. And this goes on for the rest of the values.
As Mark Rushakoff mentions, you shouldn't modify something while you're iterating over it. Change your for number in x to for number in x[:] and it will work as you expect, though. In this case you're iterating over a copy.
Don't modify a list you're iterating over. Others suggest copying the list or collecting a new list of things to remove. Instead, collect the ones you want to remain. This is faster than copying the list and removing from the copy not being iterated over, and faster than collecting the ones to remove and then removing them.
evens = []
for number in x:
if number%2 == 0:
evens += [number]
print(evens)

Categories

Resources