How to remove a string from a list that startswith prefix in python
Asked Answered
Q

3

18

I have this list of strings and some prefixes. I want to remove all the strings from the list that start with any of these prefixes. I tried:

prefixes = ('hello', 'bye')
list = ['hi', 'helloyou', 'holla', 'byeyou', 'hellooooo']
for word in list:
    list.remove(word.startswith(prexixes)

So I want my new list to be:

list = ['hi', 'holla']

but I get this error:

ValueError: list.remove(x): x not in list

What's going wrong?

Quaver answered 30/4, 2014 at 22:34 Comment(0)
M
9

Greg's solution is definitely more Pythonic, but in your original code, you perhaps meant something like this. Observe that we make a copy (using list[:] syntax) and iterate over the copy, because you should not modify a list while iterating over it.

prefixes = ('hello', 'bye')
list = ['hi', 'helloyou', 'holla', 'byeyou', 'hellooooo']
for word in list[:]:
    if word.startswith(prefixes):
        list.remove(word)
print list
Manipulator answered 30/4, 2014 at 22:37 Comment(4)
Even though Gregs answer may heve been more pythonic, I accapted this answer, because ths was precisely what I was looking for. Thanks!Quaver
Hey, thanks for that answer. Sorry for digging out this old post, but could you explain why this produces the wrong result when using for word in list: instead of for word in list[:]:Concourse
@Concourse I am very curious about this as well. I tested running for word in list and noticed that some of the strings that contained a prefix weren't being removed. However, when I tried for word in list[:], all the correct string were being removed.Rosner
I think it's because Python internally tracks the index for the loop, and when you remove an element, the index isn't updated so it skips over items.Manipulator
M
37

You can create a new list that contains all the words that do not start with one of your prefixes:

newlist = [x for x in list if not x.startswith(prefixes)]

The reason your code does not work is that the startswith method returns a boolean, and you're asking to remove that boolean from your list (but your list contains strings, not booleans).

Note that it is usually not a good idea to name a variable list, since this is already the name of the predefined list type.

Microtone answered 30/4, 2014 at 22:36 Comment(4)
Hey, I learned that startswith can take a tuple as a parameter. Cool!Microtone
I didn't actually use list as a variable name, it was just as an example here. This worked for me btw :)Quaver
And yes startswith can take tuples as a parameter as of python 2.5 :)Quaver
Thanks, I should use not more :) ...... NOT (haha, sorry for my poor sense of humor)Ernaernald
M
9

Greg's solution is definitely more Pythonic, but in your original code, you perhaps meant something like this. Observe that we make a copy (using list[:] syntax) and iterate over the copy, because you should not modify a list while iterating over it.

prefixes = ('hello', 'bye')
list = ['hi', 'helloyou', 'holla', 'byeyou', 'hellooooo']
for word in list[:]:
    if word.startswith(prefixes):
        list.remove(word)
print list
Manipulator answered 30/4, 2014 at 22:37 Comment(4)
Even though Gregs answer may heve been more pythonic, I accapted this answer, because ths was precisely what I was looking for. Thanks!Quaver
Hey, thanks for that answer. Sorry for digging out this old post, but could you explain why this produces the wrong result when using for word in list: instead of for word in list[:]:Concourse
@Concourse I am very curious about this as well. I tested running for word in list and noticed that some of the strings that contained a prefix weren't being removed. However, when I tried for word in list[:], all the correct string were being removed.Rosner
I think it's because Python internally tracks the index for the loop, and when you remove an element, the index isn't updated so it skips over items.Manipulator
H
0
print len([i for i in os.listdir('/path/to/files') if not i.startswith(('.','~','#'))])
Haler answered 1/6, 2015 at 18:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.