Often when working with lists of strings in python you might want to deal with the strings in a case insensitive manner. Today I had to fix an issue where I couldn't use somelist.remove(somestring) because the somestring variable might be in there but of a different (case)spelling.

Here was the original code:: def ss(s): return s.lower().strip() if ss(name) in names: foo(name + " was already in 'names'") names.remove(name)

The problem there is that you get an ValueError if the name variable is "peter" and the names variable is ["Peter"]. Here is my solution. Let me know what you think:


def ss(s):
   return s.lower().strip()

def ss_remove(list_, element):
   correct_element = None
   element = ss(element)
   for item in list_:
       if ss(item) == element:
           list_.remove(item)
           break

L = list('ABC')
L.remove('B')
#L.remove('c') # will fail
ss_remove(L, 'c') # will work
print L # prints ['A']

Might there be a better way?

UPDATE Check out Case insensitive list remove call (part II)

Comments

Post your own comment
Luke Plant

The following (based on a guess about how list.remove() might work) is perhaps a nicer solution:

class CaseInsensitiveString(object):
... def __init__(self, s):
....... self.s = s
... def __cmp__(self, other):
....... return cmp(self.s.lower(), other.lower())

L = list('ABC')
L.remove(CaseInsensitiveString("c"))

Andrew Wilkinson

L = list('ABC')
other = 'c'

L = [x for x in L if x.lower() != other.lower()]

# L == ['A', 'B']

Peter Bengtsson

Slim and fast but as you can see in
http://www.peterbe.com/plog/case-insensitive-list-remove-call-part-ii
I made some necessary improvements.

Jussi Salmela

How about this? Oops: I almost had time to be the first!

def ss_remove(lst,el):
return [e for e in lst if ss(e) != ss(el)]

L = list('ABC')
L = ss_remove(L, 'c') # will work
print L # prints ['A','B']

Michael

What about using a dictionary populated with (s.lower(), s)? Then your normal list is in .values(), and look-up is much faster than going through the whole list over and over. I guess it depends how often you need to look for strings disregarding case.

d = {}
d[ss(name)] = name

if ss(name) in d: print name + " there!"

Peter Bengtsson

Nice try but it doesn't preserve the order of the list.

Michael

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747 shows how to make an ordered dictionary.

Anonymous

prefer the list comp personally, but
for idx, item in enumerate(list_):
if ss(item) == element:
del list_[idx]
break
# is it a bit more efficient in worst case.

Peter Bengtsson

See the test cases on http://www.peterbe.com/plog/case-insensitive-list-remove-call-part-ii/iremove.py
and notice how unfortunately few of them are long lists. If they were really really long, a O(log n) method like this might beat the list comprehension one.

Jussi Salmela

You asked for a better way to do the removal. I interpreted it to mean 'shorter, more Pythonic' or something like that.

If we instead are talking about speed, I have a new one for you:

def f7(L,e):
....eLower = e.lower()
....eUpper = e.upper()
....L = [x for x in L if x != eLower and x != eUpper]

I don't know what kind of beast your machine is because my timings are much slower than yours. They tend to vary a little (GC?) but here's a typical run:

f1 1.59400010109
f2 2.65599989891
f3 2.23399996758
f4 0.921999931335
f5 0.905999898911
f6 1.73400020599
f7 0.43700003624

Please don't announce the winner before the race is over! :)

Jussi Salmela

This solution works for lists of single characters only! Sorry!

Jussi Salmela

How about using dictionaries? I didn't expect improvement speedwise. I was wrong. That's nothing new: I've been wrong before!

def f8(L,e):
....d = {}
....# The value could be anything, really
....d[e.lower()] = d[e.upper()] = True
....L = [x for x in L if not x in d]

Timings on my machine:
f7 0.43 - 0.48
f8 0.28 - 0.33

Jussi Salmela

This solution works for lists of single characters only! Sorry!

Your email will never ever be published.

Previous:
Shark kayak April 5, 2006 Misc. links
Next:
Case insensitive list remove call (part II) April 11, 2006 Python
Related by category:
How I run standalone Python in 2025 January 14, 2025 Python
How to resolve a git conflict in poetry.lock February 7, 2020 Python
get in JavaScript is the same as property in Python February 13, 2025 Python
Best practice with retries with requests April 19, 2017 Python
Related by keyword:
Cope with JSONDecodeError in requests.get().json() in Python 2 and 3 November 16, 2016 Python
Interesting float/int casting in Python April 25, 2006 Python
File check before delete March 7, 2008 Linux

Go to top of the page