Python Forum
weird result trying to remove numbers from a list
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
weird result trying to remove numbers from a list
#1
I'm trying to remove all the numbers from a list, but when I run the code, I get a strange result:

nums = [1, 2, 3, 4, 5]
words = ["I", "sing", "of", "arms", "and", "a", "man"]
both = nums + words

for each in both:
    if each in range(1000):
        both.remove(each)

print(both)
Output:
[2, 4, 'I', 'sing', 'of', 'arms', 'and', 'a', 'man'] Process finished with exit code 0
What are the 2 and 4 still there?
Reply
#2
You are modifying a list that you are looping through. Here's an idea of what is happening:
  • Start at position 0 with value 1
  • Remove element at position 0, all following elements are shifted back by one
  • Continue at position 1 with value 3 (you skipped over 2)
  • Remove element at position 1, all following elements...
  • Continue at position 2 with value 5 (you skipped over 4)
  • Remove element at position 2, ...
  • All following elements are preserved because they do not meet the if test.
One solution is to create an empty list and append to it all elements that you would not remove from the original list:
both = nums + words
new_list = []

for each in both:
    if each not in range(1000):
        new_list.append(each)
I haven't tested this but it should do the trick.
Reply
#3
I would approach it this way:

Take away ambiguity: 'number' is integer.

Make a plan. In spoken language: "give me items in list which are not integers".

Find the pieces:

- iterate over elements: use for-loop
- test whether element is integer: use built-in functions isinstance()
- wrap it into list comprehension

>>> lst = [1, 'one', 2, 'two']
>>> no_ints = [item for item in lst if not isinstance(item, int)]
>>> no_ints
['one', 'two'] 
EDIT: if 'number' is both integers and floats then element testing should be isinstance(item, (int, float))
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#4
The solution turned out to be fairly simple. From the official documentation:

Quote:If you need to modify the sequence you are iterating over while inside the loop (for example to duplicate selected items), it is recommended that you first make a copy. Iterating over a sequence does not implicitly make a copy. The slice notation makes this especially convenient.

This fixed the problem:
list1 = ["I", "sing", "of", "arms", "and", "a", "man"]
list2 = [1, 2, 3, 4, 5]
list3 = list1 + list2

for x in list3[:]:
    if x in range(10):
        list3.remove(x)

print(list3)
Output:
['I', 'sing', 'of', 'arms', 'and', 'a', 'man'] Process finished with exit code 0
Reply
#5
There are too much unnecessary 'actions' in code.

You create new list, then create copy of that new list and then remove items from new list to get list without integers. New list and it's copy are throw-away lists.

More efficient could be to iterate over all items in both lists and 'take out' only these which are not integers.

list_1 = ["I", "sing", "of", "arms", "and", "a", "man"]
list_2 = [1, 2, 3, 4, 5]
list_3 = []

for item in [*list_1, *list_2]: 
    if not isinstance(item, int):
        list_3.append(item)
One can do it with list comprehension as well:

list_3 =[item for item in [*list_1, *list_2] if not isinstance(item, int)]
In your code You check only for integers 0...9 which means that integers 10 and larger / less than 0 will be kept.
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#6
(Aug-26-2019, 07:52 AM)perfringo Wrote: There are too much unnecessary 'actions' in code.

You create new list, then create copy of that new list and then remove items from new list to get list without integers. New list and it's copy are throw-away lists.

More efficient could be to iterate over all items in both lists and 'take out' only these which are not integers.

list_1 = ["I", "sing", "of", "arms", "and", "a", "man"]
list_2 = [1, 2, 3, 4, 5]
list_3 = []

for item in [*list_1, *list_2]: 
    if not isinstance(item, int):
        list_3.append(item)
One can do it with list comprehension as well:

list_3 =[item for item in [*list_1, *list_2] if not isinstance(item, int)]
In your code You check only for integers 0...9 which means that integers 10 and larger / less than 0 will be kept.

In general, when do you use isinstance() and when do you use ==?
Reply
#7
(Aug-26-2019, 11:12 PM)Exsul Wrote: In general, when do you use isinstance() and when do you use ==?

They accomplish quite a different tasks:

- == compares values of two objects for equality Documentation >> The Python Language Reference >> 6. Expressions >> 6.10.1 Value Comparisons
- isinstance([i]object, classinfo[/i]) checks whether object is instance of class (or subclass) (instance of class is fancy way to say what type the object is - int, float, list etc).

You use former if you need to check equality:

>>> a = 42
>>> a == 42
True
>>> a == 43
False


You use latter for identity. As in this task - you want to eliminate all integers regardless of the value, so you check whether object is integer and act accordingly.

>>> a = 42
>>> isinstance(a, int)
True
>>> isinstance(a, float)
False
>>> isinstance(a, (int, float))
True
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  unable to remove all elements from list based on a condition sg_python 3 371 Jan-27-2024, 04:03 PM
Last Post: deanhystad
  How do I calculate a ratio from 2 numbers and return an equivalent list of about 1000 Pleiades 8 15,436 Jan-05-2024, 08:30 PM
Last Post: sgrey
  regex findall() returning weird result Radical 1 588 Oct-15-2023, 08:47 PM
Last Post: snippsat
  find random numbers that are = to the first 2 number of a list. Frankduc 23 3,012 Apr-05-2023, 07:36 PM
Last Post: Frankduc
  List of random numbers astral_travel 17 2,531 Dec-02-2022, 10:37 PM
Last Post: deanhystad
  Remove numbers from a list menator01 4 1,251 Nov-13-2022, 01:27 AM
Last Post: menator01
  [split] why can't i create a list of numbers (ints) with random.randrange() astral_travel 7 1,428 Oct-23-2022, 11:13 PM
Last Post: Pedroski55
  set.difference of two list gives empty result wardancer84 4 1,433 Jun-14-2022, 01:36 PM
Last Post: wardancer84
  Divide a number by numbers in a list. Wallen 7 7,925 Feb-12-2022, 01:51 PM
Last Post: deanhystad
  Remove empty keys in a python list python_student 7 2,899 Jan-12-2022, 10:23 PM
Last Post: python_student

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020