473,382 Members | 1,247 Online

# remove an item from string list

I have a string list

items = ['B','D','B','A','E']

Assume that I don't know the order (index) of these items. I would like to remove the second 'B' out of the list without sorting [using items.sort() ] or changing the the order of other items in the list. How can I do that?

The remove() and pop(), only take the first 'B' or I have to know the index of the second 'B' to remove second 'B' out.
Sep 14 '07 #1
12 3906
bartonc
6,596 Expert 4TB
I have a string list

items = ['B','D','B','A','E']

Assume that I don't know the order (index) of these items. I would like to remove the second 'B' out of the list without sorting [using items.sort() ] or changing the the order of other items in the list. How can I do that?

The remove() and pop(), only take the first 'B' or I have to know the index of the second 'B' to remove second 'B' out.
Expand|Select|Wrap|Line Numbers
1. >>> items = ['B','D','B','A','E']
2. >>> list(set(items))
3. ['A', 'B', 'E', 'D']
4. >>>
Hmmm... That shouldn't have reordered the list. I'll keep at it..
Sep 14 '07 #2
bartonc
6,596 Expert 4TB
Expand|Select|Wrap|Line Numbers
1. >>> items = ['B','D','B','A','E']
2. >>> list(set(items))
3. ['A', 'B', 'E', 'D']
4. >>>
Hmmm... That shouldn't have reordered the list. I'll keep at it..
Expand|Select|Wrap|Line Numbers
1. >>> for i, item in enumerate(items[:]):  #loop through a copy of the list
2. ...     try:
3. ...         j = items.index(item, i + 1)
4. ...         items.pop(j)
5. ...     except ValueError:
6. ...         pass
7. ...
8. >>> items
9. ['B', 'D', 'A', 'E']
10. >>>
Sep 14 '07 #3
Expand|Select|Wrap|Line Numbers
1. >>> items = ['B','D','B','A','E']
2. >>> list(set(items))
3. ['A', 'B', 'E', 'D']
4. >>>
Hmmm... That shouldn't have reordered the list. I'll keep at it..
I mentioned that I did not know the order of the list in items, I only knew that there was two 'B' in the list. In your case, we would have to know the order of all items.
Sep 14 '07 #4
Expand|Select|Wrap|Line Numbers
1. >>> for i, item in enumerate(items[:]):  #loop through a copy of the list
2. ...     try:
3. ...         j = items.index(item, i + 1)
4. ...         items.pop(j)
5. ...     except ValueError:
6. ...         pass
7. ...
8. >>> items
9. ['B', 'D', 'A', 'E']
10. >>>
Thank you very much. However, is there a simpler way to pop second 'B' out without using loop?
Sep 14 '07 #5
bartonc
6,596 Expert 4TB
Thank you very much. However, is there a simpler way to pop second 'B' out without using loop?
Two tricks here:
1) Start searching for the index one past the location of the first occurrence.
2) Wrap the index() method in a try block in case it fails.
Expand|Select|Wrap|Line Numbers
1. >>> items = ['B','D','B','A','E']
2. >>> try:
3. ...     j = items.index('B', 1)  # one past the location of the first occurrence
4. ...     items.pop(j)
5. ... except ValueError:
6. ...     pass
7. ...
8. >>> items
9. ['B', 'D', 'A', 'E']
10. >>>
Sep 14 '07 #6
Two tricks here:
1) Start searching for the index one past the location of the first occurrence.
2) Wrap the index() method in a try block in case it fails.
Expand|Select|Wrap|Line Numbers
1. >>> items = ['B','D','B','A','E']
2. >>> try:
3. ...     j = items.index('B', 1)  # one past the location of the first occurrence
4. ...     items.pop(j)
5. ... except ValueError:
6. ...     pass
7. ...
8. >>> items
9. ['B', 'D', 'A', 'E']
10. >>>
Thank you. I got the trick
Sep 14 '07 #7
I just thought another way to approach the problem. Could I determine all indexs of 'B' in the list, so when there were numberous 'B's in the list I would be able to pop B at any certain index?
Sep 14 '07 #8
bvdet
2,851 Expert Mod 2GB
I just thought another way to approach the problem. Could I determine all indexs of 'B' in the list, so when there were numberous 'B's in the list I would be able to pop B at any certain index?
I have used this function many times:
Expand|Select|Wrap|Line Numbers
1. """
2. Return an index list of all occurrances of 'item' in string/list 's'.
3. Optional start search position 'i'
4. """
5. def indexList(s, item, i=0):
6.     i_list = []
7.     while True:
8.         try:
9.             i = s.index(item, i)
10.             i_list.append(i)
11.             i += 1
12.         except:
13.             break
14.     return i_list
>>> items = ['B','D','B','A','E']
>>> indexList(items, 'B')
[0, 2]
>>>
Sep 14 '07 #9
ilikepython
844 Expert 512MB
I have used this function many times:
Expand|Select|Wrap|Line Numbers
1. """
2. Return an index list of all occurrances of 'item' in string/list 's'.
3. Optional start search position 'i'
4. """
5. def indexList(s, item, i=0):
6.     i_list = []
7.     while True:
8.         try:
9.             i = s.index(item, i)
10.             i_list.append(i)
11.             i += 1
12.         except:
13.             break
14.     return i_list
>>> items = ['B','D','B','A','E']
>>> indexList(items, 'B')
[0, 2]
>>>
I don't know about you, but I think this is clearer:
Expand|Select|Wrap|Line Numbers
1. def indexList(s, item, start = 0):
2.     i_list = []
3.     for (i, obj) in enumerate(s[start:]):
4.         if obj == item:
5.             i_list.append(i + start)
6.     return i_list
7.
or with map:
Expand|Select|Wrap|Line Numbers
1. def indexList(s, item, start = 0):
2.     return filter(lambda x: x, map(lambda (i, obj): i + start if obj == item else None, enumerate(s[start:]))) # i think i over did it
3.
I think yours is faster for larger lists though.

EDIT:
List comprhension is definately clearer:
Expand|Select|Wrap|Line Numbers
1. def indexList(s, item, start = 0):
2.     return [i + start for (i, obj) in enumerate(s[start:]) if obj == item]
3.
Sep 14 '07 #10
bvdet
2,851 Expert Mod 2GB
I don't know about you, but I think this is clearer:
Expand|Select|Wrap|Line Numbers
1. def indexList(s, item, start = 0):
2.     i_list = []
3.     for (i, obj) in enumerate(s[start:]):
4.         if obj == item:
5.             i_list.append(i + start)
6.     return i_list
7.
or with map:
Expand|Select|Wrap|Line Numbers
1. def indexList(s, item, start = 0):
2.     return filter(lambda x: x, map(lambda (i, obj): i + start if obj == item else None, enumerate(s[start:]))) # i think i over did it
3.
I think yours is faster for larger lists though.

EDIT:
List comprhension is definately clearer:
Expand|Select|Wrap|Line Numbers
1. def indexList(s, item, start = 0):
2.     return [i + start for (i, obj) in enumerate(s[start:]) if obj == item]
3.
Thanks ilikepython. I like your code. I have not done any tests for efficiency. It's good to see alternate methods that accomplish the same goal.
Sep 14 '07 #11
ghostdog74
511 Expert 256MB
I have a string list

items = ['B','D','B','A','E']

Assume that I don't know the order (index) of these items. I would like to remove the second 'B' out of the list without sorting [using items.sort() ] or changing the the order of other items in the list. How can I do that?

The remove() and pop(), only take the first 'B' or I have to know the index of the second 'B' to remove second 'B' out.
go with the basics. The basics are very important
Expand|Select|Wrap|Line Numbers
1. >>> items = ['B','D','B','A','E']
2. >>> start=items.index('B') #get the first "B" position
3. >>> print start
4.
5. >>> second = items[start+1:].index("B") # get the second "B"
6. >>> print second
7. 1
8. >>> index_to_remove = second + 1 #add 1 to get exact position of second "B" since we started search 1 position after the first "B"
9. >>> items.pop(index_to_remove)
10. 'B'
11. >>> items
12. ['B', 'D', 'A', 'E']
13. >>>
14.
Sep 15 '07 #12
ilikepython
844 Expert 512MB
Thanks ilikepython. I like your code. I have not done any tests for efficiency. It's good to see alternate methods that accomplish the same goal.
The only problem is it doesn't work for patterns. Like, to search for "ACC" in "ACACCAAACC".
Sep 15 '07 #13