1

Is there a way to make a list comprehension to search for a string being case insensitive?

What I do now, which is subpar is:


original_list = ['NAME', 'NUMBER', 'name', 'number', 'Name', 'NaMe', 'place']

filtered_list = [x for x in LIST if "NAME" in x or "name" in x]

This example would exclude "Name" and "NaMe" (which I want to be included) for example. The idea is to use a list comprehension and have a short and concise way of doing this.

I would like to do something like this:


case_insensitive_list = [x for x in LIST if 'name'.caseinsensitive() in x]

(it seems after the second OR the list comprehension begins to behave weird.)

I CANNOT use the str.upper() strategy, I need to retain the case of the original list.

I am expecting a simple list comprehension with a case agnostic string matching condition.

My expected outcome:

['NAME', 'name', 'Name', 'NaMe']

3 Answers3

3

I CANNOT use the str.upper() strategy, I need to retain the case of the original list.

The original list is not affected if you do this in the if condition only:

LIST = ['NAME', 'NUMBER', 'name', 'number', 'Name', 'NaMe', 'place']

filtered_list = [x for x in LIST if "name" in x.lower()]


print(filtered_list)
# ['NAME', 'name', 'Name', 'NaMe']


print(LIST)
# ['NAME', 'NUMBER', 'name', 'number', 'Name', 'NaMe', 'place']
webelo
  • 1,646
  • 1
  • 14
  • 32
  • But the OP didn't want "Name" or "NaMe" to be matched. – quamrana Jun 20 '23 at 16:09
  • When OP says, "this example will exclude" are they referring to the proposed solution, `[x for x in LIST if "NAME" in x or "name" in x]`, which will indeed exclude `"Name"` and `"NaMe"`? – webelo Jun 20 '23 at 16:13
  • 2
    I think OP means "my existing code would exclude `Name` and `NaMe`, therefore my existing code is suboptimal". As opposed to "my target solution would exclude them". – slothrop Jun 20 '23 at 16:13
  • This answers my question. I do want "Name" and "NaMe" to be matched. Thank you – Quant1892387 Jun 20 '23 at 16:16
2

Pretty simple, you just need to turn each item in the list to uppercase and check against the uppercase "NAME" list this.

It might also be wise to get in the habit of not calling lists LIST or list.

my_list = ['NAME', 'NUMBER', 'name', 'number', 'Name', 'NaMe', 'place']

filtered_list = [x for x in my_list if "NAME"==x.upper()]

print(filtered_list)
# ['NAME', 'name', 'Name', 'NaMe']
Johnny John Boy
  • 3,009
  • 5
  • 26
  • 50
  • Thank you. Why use if "NAME"==x.upper() instead of "NAME" in x.upper? – Quant1892387 Jun 20 '23 at 16:20
  • 1
    In is going to check a sequence so typically is used when you want to know if a value is IN something, be it a list OR a substring within a string. == is absolute, it will only match if the value is equal. Unless you want a positive match on an item in your list like my_list = ['NAME', 'NUMBER', 'name', 'number', 'Name', 'NaMe', 'hidden_name_in_item', 'place'] then I would always use ==. – Johnny John Boy Jun 20 '23 at 17:38
1

You could always use the re module.

import re

LIST = ['NAME', 'NUMBER', 'name', 'number', 'Name', 'NaMe', 'place']
filtered_list = [x for x in LIST if re.match("name", x, re.IGNORECASE)]
chepner
  • 497,756
  • 71
  • 530
  • 681