I'm really beginer of python and i'm wondering how to remove all same elements that i want
I know i can remove a one element with list.remove('target') but it just happen once,
I googled about it but they just say use 'for' or 'while' but i don't know how to do it with a smart way
example , when i have list "apple" i want to make it "ale" with parameter'p'
I tried
list = ['a','p','p','l','e']
for i in list:
list.remove('p')
but i got error that 'ValueError: list.remove(x): x not in list'
(My English might sucks because i'm Korean :( and it's my first ask in stackoverflow )
First you should not be using list as a variable name as list is a built-in type in python.
See: Built-in types in python
For your question, you can use list comprehension for this.
eg:
my_list = ['a','p','p','l','e']
element_to_remove = 'p'
new_list = [item for item in my_list if item != element_to_remove]
# new_list = ['a', 'l', 'e']
You can convert the list to set (so that there will be no repetitions) and convert it back to list. After, remove the element you want.
my_list = ['a','p','p','l','e']
my_list2 = my_list(set(my_list))
my_list.remove('p')
Try list comprehension:
[i for i in l if i not in ('p',)]
where l is your list.
Related
This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 6 months ago.
I am trying to write simple code to print an item of a list and remove it after printing:
list = ['a', 'b', 'c']
for i in list:
print(i)
list.remove(i)
But output is weird:
a
c
Why is output thay way?
When you iterate over a list, you get the items in order of their indices (item 0, item 1, item 2, etc). When you remove an item from a list, the indices of all the items after that shift by one.
In the first iteration, the list is ['a', 'b', 'c'], and i is list[0].
During the first iteration, you remove 'a'.
In the second iteration, the list is ['b', 'c'], and i is list[1]. You get 'c' instead of 'b' because 'c' is now at index 1.
If you want to remove each item as you iterate, the better approach would be to iterate in a while loop as long as the list contains items, and pop as you print:
my_list = ['a', 'b', 'c']
while my_list:
print(my_list.pop(0))
In many cases, it's better to do the thing you want to do in the iteration, and then clear the list:
for i in my_list:
print(i)
my_list.clear()
You're currently iterating while removing the items, if you want alter the list while reading it then probably you want to use the length "as index":
list = ['a', 'b', 'c']
while len(list):
# pop does what you want: read the element at index [i] and remove it from the list
print(list.pop(0))
Output:
a
b
c
Explanation
the reason the output seems strange it's because you are removing items when iterating over a list.
the problem here is that python iterates checking for the index.
Consider this example:
lst = [32,43,2]
for x in lst:
lst.pop(0)
print(x,lst)
Outputs
32 [43, 2]
2 [2]
here you can see the problem. in the first iteration it took the first item that was removed, all ok. The problem starts with the second iteration.
The iterator thinks the index to go is 1 (2nd element) but it's actually the 1st since the first element was removed.
You can fix it also by iterating the reversed list as the index cannot change.
also see this question for more information
Possible solutions
You should iterate over a copy instead:
for x in mylist.copy():
mylist.remove(x)
You could also use a while loop and list.pop.
while mylist:
print(mylist.pop(0))
Advice
Before leaving, I would like to give some advice.
Don't use builtin as variable names, it causes confusion and could cause conflict in your code if it uses those builtin names.
I would advice to clear the list after the loop using the list.clear() method.
Use the list.pop method if you want to know a value and remove it at the same time.
Useful links
python datastructures official documentation
python list w3school
linuxhint python list methods
Why does list(str) behaves as string here when [str] doesn't?
Is there a difference between these methods
Before someone marks this as a duplicate do link the answer because I've spent a fair bit of time scrawling through stackoverflow!
code
x = 'ar'
'a' in list(x)
#True
'a' in [x]
#False
l = list(x)
'a' in l
#True
type(list(x))
#list
type([x])
#list
This is because list() converts the string to a list where each letter is one element. But [] creates a list where the things inside are the elements. List() is converting the string to a list whereas [] is just putting the string in a list.
You can use debug output for clarifying such things. Like this:
x = 'ar'
print(list(x))
print([x])
Prints this:
['a', 'r']
['ar']
Then let's think logically. list(x) is a constructor of a list from the string, it creates a list of all characters of a given string. And [x] just creates a list with one item: x.
Because you are asking if the element 'a' is in the list. Which it is not, your only element is 'ar'. If you print([x]) the result should be ['ar']
[x] creates a single-element list, where the element is x. So if x = 'ar', then the resulting list is ['ar'].
list(x) casts the variable x into a list. This can work on any iterable object, and strings are iterable. The resulting list is ['a', 'r'].
The element 'a' is in the second list but not the first.
I have a list like this:
my_list = ['a,b,c']
Then I wanna reformat the list to
new_list = ["a","b","c"]
Can someone give a hand, I'm a newbie in Python. Thanks!
You can try this:-
my_list = ['a,b,c']
new_list = my_list[0].split(',')
print(new_list)
Output:-
['a', 'b', 'c']
Please note that the first list holds only 1 item which is a string.
So, you can use split() method to split the string into an array as followings:
my_list = ['a,b,c']
new_list = my_list[0].split(",")
## ^^^ This is to get the first item since the array has only 1 item
So I am getting a list index out of range error in python again, and I can't figure out what's wrong.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
f1 = open("membrane_GO.txt","r")
new_list1 = f1.readlines()
new_list2 = new_list1
for i in range(len(new_list1)):
if "Reactome" in new_list1[i]:
new_list2.pop(i)
print new_list2
f1.close()
I made sure that the a duplicated list is being modified as the primary list is iterated over, so that can't be the problem.
Appreciate any help
Thanks :)
You only duplicated a reference to the list. If you want to make a separate copy of a list, use slices: list2 = list1[:] or look into the deepcopy module.
When you pop, the array size goes down. That means if the list has length 10, and you pop(0), then the list has length 9. If you then pop(9), which doesn't exist it will give you an out of bounds error.
Example:
>>> x = [0,1,2,3,4]
>>> print x, len(x)
[0,1,2,3,4], 5
>>> x.pop(0)
>>> print x, len(x)
[1,2,3,4], 4
This is an error in your case because you go from 0 to len(new_list1).
The approach I advise you to take is to create a new list where "Reactome" is not in new_list1[i].
You can do this easily in a list comprehension.
with open("membrane_GO.txt","r") as f:
lines = [line for line in f.readlines() if "Reactome" not in line]
print lines
Assume that your list is initially ['a', 'b', 'c'],
then list1 = list2 = ['a', 'b', 'c']
Then you perform iteration for len(list2), ie 3 times,
Then i will take values 0, 1, and 2.
In each iteration you are removing one element from list1.
i = 0
remove list1[0]
new list = ['b', 'c']
i = 1
remove list1[1]
new list = ['b']
i = 2
remove list[2] which does not exist.
So you will get a index out of bound error
Just to add to TigerHawks answer:
Because you have only duplicated the reference (not the list itself), when you pop() an element out of new_list2, you also remove it from new_list1 beceause they're both references to the same list.
Say there are 'n' elements in new_list1 at the start of the loop. It will run for 'n' iterations.
Suppose then that you pop an element out of new_list2 (and so out of new_list1 as well), within the loop, you will get an index out of range error when the loop tries to access the 'nth' element of a list which now only has 'n-1' elements in it
For this to work properly use slicing to copy the list:
new_list2 = new_list1[:]
Incidentally, for i in range(len(new_list1)): is considered un-pythonic, I believe. A 'better' way would be to use enumerate:
for index, element in enumerate(new_list1):
if "Reactome" in element:
new_list2.pop(index)
filtered_list = ['PerezHilton', 'tomCruise', 'q', 'p']
#BIO[user]['follows'] is just a list of strings say ['a', 'b', 'katieh']
#specs is also a string say eg. 'katieh'
for user in filtered_list:
if specs not in BIO[user]['follows']:
filtered_list.remove(user)
The above code for some reson gives this error "ValueError: list.remove(x): x not in list" but clearly 'p' is in the list so why is it not detecting 'p' but it is finding 'q'??
Im soo stumped but any help is appreciated, thanks
** SORRY i FIXED IT NOW *
The list comprehension that does this correctly in one line is at the bottom of the post. Here's some insight into the problem first.
Don't do things like:
for item in list_:
list_.remove(item)
because bad and confusing things happen.
>>> list_ = range(10)
>>> for item in list_:
... list_.remove(item)
...
>>> list_
[1, 3, 5, 7, 9]
Every time you remove an item, you change the indexes for the rest of the items which messes up the loop. One good way to remove items from a list while you're traversing it is to do it by index and work backwards so that removals don't affect the rest of the iterations. This is better because if you remove the 9'th element, then the 8'th element is still the 8'th element but the 10'th element becomes the 9'th element. If you've already dealt with that element, then you don't care what its index is.
>>> list_ = range(10)
>>> for i in xrange(len(list_) - 1, -1, -1):
... del list_[i]
...
>>> list_
[]
Or with a while loop:
i = len(list_)
while i:
i -= 1
del list_[i]
So in your case, the code would look something like
users[:] = [user for user in users if specs in BIO[user]['follows']]
because this is a filtering job and those are best done with list comprehensions. The point of the [:] is that it assigns to a slice of the list instead of clobbering the reference to the list. This means that every other reference to the list will be updated. It's essentially in-place, except that a copy is made before overwriting the original list. For the sake of completeness, here's how to do it with a while loop.
i = len(users)
while i:
i -= 1
if specs not in BIO[users[i]]['follows']:
del users[i]
You could do this if you wanted it done in place. No copy of the list is made here.
Why are you iterating?
>>> un = ['PerezHilton', 'tomCruise', 'q', 'p']
>>> un.remove('p')
>>> un
['PerezHilton', 'tomCruise', 'q']