how to remove multiple occurrences of a string within a list?

B

bahoo

Hi,

I have a list like ['0024', 'haha', '0024']
and as output I want ['haha']

If I
myList.remove('0024')

then only the first instance of '0024' is removed.

It seems like regular expressions is the rescue, but I couldn't find
the right tool.

Thanks!
bahoo
 
K

kyosohma

It depends on your application, but a 'set' might really be what you
want, as opposed to a list.
s = set(["0024","haha","0024"])
s

set(["0024","haha"])>>> s.remove("0024")
set(["haha"])

If you want, you can also loop over the list, like so:

counter = 0
your_list = ["0024","haha","0024"]
for i in your_list:
if i == '0024':
your_list.pop(counter)
counter += 1


Mike
 
T

Thomas Nelson

bahoo said:
Hi,

I have a list like ['0024', 'haha', '0024']
and as output I want ['haha']

If I
myList.remove('0024')

then only the first instance of '0024' is removed.

It seems like regular expressions is the rescue, but I couldn't find
the right tool.

Thanks!
bahoo

It's hard to imagine using regular expressions here. Here's a simple
attempt:

def removeall(mylist,obj):
while obj in mylist:
mylist.remove(obj)

Or, if you don't need the changes in place:

[x for x in mylist if x!= obj]

Tom
 
T

Thomas Nelson

It depends on your application, but a 'set' might really be what you
want, as opposed to a list.
s = set(["0024","haha","0024"])
s
set(["0024","haha"])>>> s.remove("0024")
set(["haha"])

If you want, you can also loop over the list, like so:

counter = 0
your_list = ["0024","haha","0024"]
for i in your_list:
if i == '0024':
your_list.pop(counter)
counter += 1

Mike

This method doesn't work..... if i=='l':
.... li.pop(count)
.... coun += 1
....
'l'
'l'['h', 'e', 'l', 'o', ' ', 'a', 'r', 'r', 'y']

because the indexes change as you pop, it gets some of them but not
all.
 
K

kyosohma

It depends on your application, but a 'set' might really be what you
want, as opposed to a list.
s = set(["0024","haha","0024"])
s
set(["0024","haha"])>>> s.remove("0024")
set(["haha"])

If you want, you can also loop over the list, like so:

counter = 0
your_list = ["0024","haha","0024"]
for i in your_list:
if i == '0024':
your_list.pop(counter)
counter += 1

Mike

If you want to get really fancy, you could do a list comprehension
too:

your_list = ["0024","haha","0024"]
new_list = [i for i in your_list if i != '0024']

Mike
 
7

7stud

Hi,

I have a list like ['0024', 'haha', '0024']
and as output I want ['haha']

If I
myList.remove('0024')

then only the first instance of '0024' is removed.

It seems like regular expressions is the rescue, but I couldn't find
the right tool.

Thanks!
bahoo

Here are a couple of ways:

target = "0024"
l = ["0024", "haha", "0024"]

------------------------------------
while(True):
try:
l.remove(target)
except ValueError:
break

print l
-------------------------------------

for index, val in enumerate(l):
if val==target:
del l[index]

print l
 
S

Steve Holden

bahoo said:
It depends on your application, but a 'set' might really be what you
want, as opposed to a list.
s = set(["0024","haha","0024"])
s
set(["0024","haha"])>>> s.remove("0024")
set(["haha"])

This sounds cool.
But is there a command I can convert the "set" back to a "list"?
That would be list(). So what you want is

s = set(["0024","haha","0024"])
s.remove("0024")
l = list(s)

or something like it. It seems, a priori, unlikely that you only want to
remove items with that specific value, Is this part of some larger problem?

regards
Steve
 
I

irstas

It depends on your application, but a 'set' might really be what you
want, as opposed to a list.
s = set(["0024","haha","0024"])
s
set(["0024","haha"])>>> s.remove("0024")
set(["haha"])

This sounds cool.
But is there a command I can convert the "set" back to a "list"?

Beware that converting a list to set and then back to list won't
preserve the order of the items, because the set-type loses the order.
 
B

bahoo

bahoo said:
It depends on your application, but a 'set' might really be what you
want, as opposed to a list.
s = set(["0024","haha","0024"])
s
set(["0024","haha"])>>> s.remove("0024")
s
set(["haha"])
This sounds cool.
But is there a command I can convert the "set" back to a "list"?

That would be list(). So what you want is

s = set(["0024","haha","0024"])
s.remove("0024")
l = list(s)

or something like it. It seems, a priori, unlikely that you only want to
remove items with that specific value, Is this part of some larger problem?

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden
Recent Ramblings http://holdenweb.blogspot.com

Thanks for all the suggestions.
The larger problem is, I have a list of strings that I want to remove
from another list of strings.
So I guess what I will do is, use a for loop, and within the for loop,
do the "list" to "set" and then back to "list".
 
B

bahoo

I have a list like ['0024', 'haha', '0024']
and as output I want ['haha']
If I
myList.remove('0024')
then only the first instance of '0024' is removed.
It seems like regular expressions is the rescue, but I couldn't find
the right tool.
Thanks!
bahoo

Here are a couple of ways:

target = "0024"
l = ["0024", "haha", "0024"]

------------------------------------
while(True):
try:
l.remove(target)
except ValueError:
break

print l
-------------------------------------

for index, val in enumerate(l):
if val==target:
del l[index]

print l

This latter suggestion (with the for loop) seems to be buggy: if there
are multiple items in the list "l" equal to "target", then only the
first one will be removed!

Thanks anyways.
 
S

Steven Bethard

bahoo said:
The larger problem is, I have a list of strings that I want to remove
from another list of strings.

If you don't care about the resulting order::
>>> items = ['foo', 'bar', 'baz', 'bar', 'foo', 'frobble']
>>> to_remove = ['foo', 'bar']
>>> set(items) - set(to_remove)
set(['frobble', 'baz'])

If you do care about the resulting order::
>>> to_remove = set(to_remove)
>>> [item for item in items if item not in to_remove]
['baz', 'frobble']

STeVe
 
B

bahoo

bahoo said:
The larger problem is, I have a list of strings that I want to remove
from another list of strings.

If you don't care about the resulting order::
items = ['foo', 'bar', 'baz', 'bar', 'foo', 'frobble']
to_remove = ['foo', 'bar']
set(items) - set(to_remove)
set(['frobble', 'baz'])

If you do care about the resulting order::
to_remove = set(to_remove)
[item for item in items if item not in to_remove]
['baz', 'frobble']

STeVe

This is amazing. I love python!
 
S

Steven D'Aprano

Hi,

I have a list like ['0024', 'haha', '0024']
and as output I want ['haha']

If I
myList.remove('0024')

then only the first instance of '0024' is removed.

There are a whole heap of ways of doing this. They all have in common the
idea of doing something over and over again until you're finished.

Here's one way, using a loop in a try...except block.

try:
while True:
myList.remove('0024')
# raises an exception when the target isn't in the list any more
except ValueError:
pass # we're done

It seems like regular expressions is the rescue,

Since when did reg exes operate on lists?
 
H

Hendrik van Rooyen

It depends on your application, but a 'set' might really be what you
want, as opposed to a list.
s = set(["0024","haha","0024"])
s

set(["0024","haha"])>>> s.remove("0024")

set(["haha"])

This sounds cool.
But is there a command I can convert the "set" back to a "list"?

Here is a general way to find the duplicates:
duplist [1, 2, 3, 4, 'haha', 1, 2, 3, 4, 5]
copylist = duplist[:]
for x in duplist:
del(copylist[copylist.index(x)])
if x in copylist:
fullset.remove(x)
fullset set([5, 'haha'])
list(fullset) [5, 'haha']

hth - Hendrik
 
A

Amit Khemka

Hi,

I have a list like ['0024', 'haha', '0024']
and as output I want ['haha']

If I
myList.remove('0024')

then only the first instance of '0024' is removed.

To remove all items with multiple occurances in myList:

list(set(myList) - set([x for x in myList if myList.count(x)>1]))

cheers,
--
 
7

7stud

target = "0024"
l = ["0024", "haha", "0024"]

for index, val in enumerate(l):
if val==target:
del l[index]

This latter suggestion (with the for loop) seems to be buggy: if there
are multiple items in the list "l" equal to "target", then only the
first one will be removed!

Thanks anyways.

Prove it.
 
S

Steven D'Aprano

target = "0024"
l = ["0024", "haha", "0024"]

for index, val in enumerate(l):
if val==target:
del l[index]

This latter suggestion (with the for loop) seems to be buggy: if there
are multiple items in the list "l" equal to "target", then only the
first one will be removed!

Thanks anyways.

Prove it.

Try replacing l = ["0024", "haha", "0024"]
with

l = ["0024", "0024", "haha"]

and re-running the code.


Actually, the description of the bug isn't quite right. The behaviour of
the for loop isn't defined -- sometimes it will work, sometimes it won't,
depending on how many items there are, and which of them are equal to the
target.

The reason it is buggy is that it is deleting items from the same list it
is trying to enumerate over. The only safe way to do that is to iterate
over the list backwards, only deleting items you've already seen and won't
go over again:

for i in range(len(my_list), -1, -1)):
if condition:
del my_list


I don't think reversed() will help you here, but I can't check for sure
because I've only got Python 2.3 on this system.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top