Case insensitive 'in' - Python
I love using the expression
if 'MICHAEL89' in USERNAMES:
...
where USERNAMES
is a list
Is there any way to match items with case insensitivity or do I need to use a custom method? Just wondering if there is need to write extra code for this.
Thanks to everyone!
python list case-insensitive
add a comment |
I love using the expression
if 'MICHAEL89' in USERNAMES:
...
where USERNAMES
is a list
Is there any way to match items with case insensitivity or do I need to use a custom method? Just wondering if there is need to write extra code for this.
Thanks to everyone!
python list case-insensitive
add a comment |
I love using the expression
if 'MICHAEL89' in USERNAMES:
...
where USERNAMES
is a list
Is there any way to match items with case insensitivity or do I need to use a custom method? Just wondering if there is need to write extra code for this.
Thanks to everyone!
python list case-insensitive
I love using the expression
if 'MICHAEL89' in USERNAMES:
...
where USERNAMES
is a list
Is there any way to match items with case insensitivity or do I need to use a custom method? Just wondering if there is need to write extra code for this.
Thanks to everyone!
python list case-insensitive
python list case-insensitive
edited Mar 18 '14 at 19:11
Connor
51.1k22113128
51.1k22113128
asked Sep 2 '10 at 13:56
RadiantHexRadiantHex
9,62935122223
9,62935122223
add a comment |
add a comment |
7 Answers
7
active
oldest
votes
if 'MICHAEL89' in (name.upper() for name in USERNAMES):
...
Alternatively:
if 'MICHAEL89' in map(str.upper, USERNAMES):
...
Or, yes, you can make a custom method.
7
if 'CaseFudge'.lower() in [x.lower() for x in list]
– fredley
Sep 2 '10 at 14:00
38
[...]
creates the whole list.(name.upper() for name in USERNAMES)
would create only a generator and one needed string at a time - massive memory savings if you're doing this operation a lot. (even more savings, if you simply create a list of lowercase usernames that you reuse for checking every time)
– viraptor
Sep 2 '10 at 14:06
2
Prefer to lower all keys when building the dict, for performance reasons.
– Ryan
May 1 '13 at 6:27
if [x.lower() for x in list] is a list comprehension, is (name.upper() for name in USERNAMES) a tuple comprehension? Or does it have another name?
– otocan
Apr 19 '18 at 8:48
1
@otocan It's a generator expression.
– nmichaels
Apr 19 '18 at 13:13
|
show 1 more comment
I would make a wrapper so you can be non-invasive. Minimally, for example...:
class CaseInsensitively(object):
def __init__(self, s):
self.__s = s.lower()
def __hash__(self):
return hash(self.__s)
def __eq__(self, other):
# ensure proper comparison between instances of this class
try:
other = other.__s
except (TypeError, AttributeError):
try:
other = other.lower()
except:
pass
return self.__s == other
Now, if CaseInsensitively('MICHAEL89') in whatever:
should behave as required (whether the right-hand side is a list, dict, or set). (It may require more effort to achieve similar results for string inclusion, avoid warnings in some cases involving unicode
, etc).
3
that doesn't work for dict try if CaseInsensitively('MICHAEL89') in {'Michael89':True}:print "found"
– Xavier Combelle
Sep 2 '10 at 14:56
2
Xavier: You would needCaseInsensitively('MICHAEL89') in {CaseInsensitively('Michael89'):True}
for that to work, which probably doesn't fall under "behave as required".
– Gabe
Sep 2 '10 at 15:07
So much for there being only 1 obvious way to do it. This feels heavy unless it's going to be used a lot. That said, it's very smooth.
– nmichaels
Sep 2 '10 at 17:56
1
@Nathon, it seems to me that having to invasively alter the container is the "feels heavy" operation. A completely non-invasive wrapper: how much "lighter" than this could one get?! Not much;-). @Xavier, RHS's that are dicts or sets with mixed-case keys/items need their own non-invasive wrappers (part of the shortetc.
and "require more effort" parts of my answer;-).
– Alex Martelli
Sep 2 '10 at 18:14
My definition of heavy involves writing quite a bit of code to make something that will only be used once, where a less robust but much shorter version would do. If this is going to be used more than once, it's perfectly sensible.
– nmichaels
Sep 2 '10 at 18:35
add a comment |
Usually (in oop at least) you shape your object to behave the way you want. name in USERNAMES
is not case insensitive, so USERNAMES
needs to change:
class NameList(object):
def __init__(self, names):
self.names = names
def __contains__(self, name): # implements `in`
return name.lower() in (n.lower() for n in self.names)
def add(self, name):
self.names.append(name)
# now this works
usernames = NameList(USERNAMES)
print someone in usernames
The great thing about this is that it opens the path for many improvements, without having to change any code outside the class. For example, you could change the self.names
to a set for faster lookups, or compute the (n.lower() for n in self.names)
only once and store it on the class and so on ...
add a comment |
I think you have to write some extra code. For example:
if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES):
...
In this case we are forming a new list with all entries in USERNAMES
converted to upper case and then comparing against this new list.
Update
As @viraptor says, it is even better to use a generator instead of map
. See @Nathon's answer.
Or you could useitertools
functionimap
. It's much faster than a generator but accomplishes the same goal.
– wheaties
Sep 2 '10 at 14:24
add a comment |
You could do
matcher = re.compile('MICHAEL89', re.IGNORECASE)
filter(matcher.match, USERNAMES)
Update: played around a bit and am thinking you could get a better short-circuit type approach using
matcher = re.compile('MICHAEL89', re.IGNORECASE)
if any( ifilter( matcher.match, USERNAMES ) ):
#your code here
The ifilter
function is from itertools, one of my favorite modules within Python. It's faster than a generator but only creates the next item of the list when called upon.
Just to add, the pattern might need to be escaped, since it might contain characters like ".","?", which has specail meaning in regular expression patterns. use re.escape(raw_string) to do it
– Iching Chang
Jan 8 '17 at 23:29
add a comment |
str.casefold
is recommended for case-insensitive string matching. @nmichaels's solution can trivially be adapted.
Use either:
if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):
Or:
if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):
As per the docs:
Casefolding is similar to lowercasing but more aggressive because it
is intended to remove all case distinctions in a string. For example,
the German lowercase letter 'ß' is equivalent to "ss". Since it is
already lowercase,lower()
would do nothing to 'ß';casefold()
converts it to "ss".
add a comment |
Here's one way:
if string1.lower() in string2.lower():
...
For this to work, both string1
and string2
objects must be of type string
.
4
AttributeError: 'list' object has no attribute 'lower'
– Jeff
Oct 13 '17 at 12:26
@Jeff that's because one of your elements is a list, and both objects should be a string. Which object is a list?
– User
yesterday
I would up vote you, but I cannot unless you edit your answer. You are absolutely right.
– Jeff
yesterday
@Jeff I added clarification.
– User
yesterday
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f3627784%2fcase-insensitive-in-python%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
7 Answers
7
active
oldest
votes
7 Answers
7
active
oldest
votes
active
oldest
votes
active
oldest
votes
if 'MICHAEL89' in (name.upper() for name in USERNAMES):
...
Alternatively:
if 'MICHAEL89' in map(str.upper, USERNAMES):
...
Or, yes, you can make a custom method.
7
if 'CaseFudge'.lower() in [x.lower() for x in list]
– fredley
Sep 2 '10 at 14:00
38
[...]
creates the whole list.(name.upper() for name in USERNAMES)
would create only a generator and one needed string at a time - massive memory savings if you're doing this operation a lot. (even more savings, if you simply create a list of lowercase usernames that you reuse for checking every time)
– viraptor
Sep 2 '10 at 14:06
2
Prefer to lower all keys when building the dict, for performance reasons.
– Ryan
May 1 '13 at 6:27
if [x.lower() for x in list] is a list comprehension, is (name.upper() for name in USERNAMES) a tuple comprehension? Or does it have another name?
– otocan
Apr 19 '18 at 8:48
1
@otocan It's a generator expression.
– nmichaels
Apr 19 '18 at 13:13
|
show 1 more comment
if 'MICHAEL89' in (name.upper() for name in USERNAMES):
...
Alternatively:
if 'MICHAEL89' in map(str.upper, USERNAMES):
...
Or, yes, you can make a custom method.
7
if 'CaseFudge'.lower() in [x.lower() for x in list]
– fredley
Sep 2 '10 at 14:00
38
[...]
creates the whole list.(name.upper() for name in USERNAMES)
would create only a generator and one needed string at a time - massive memory savings if you're doing this operation a lot. (even more savings, if you simply create a list of lowercase usernames that you reuse for checking every time)
– viraptor
Sep 2 '10 at 14:06
2
Prefer to lower all keys when building the dict, for performance reasons.
– Ryan
May 1 '13 at 6:27
if [x.lower() for x in list] is a list comprehension, is (name.upper() for name in USERNAMES) a tuple comprehension? Or does it have another name?
– otocan
Apr 19 '18 at 8:48
1
@otocan It's a generator expression.
– nmichaels
Apr 19 '18 at 13:13
|
show 1 more comment
if 'MICHAEL89' in (name.upper() for name in USERNAMES):
...
Alternatively:
if 'MICHAEL89' in map(str.upper, USERNAMES):
...
Or, yes, you can make a custom method.
if 'MICHAEL89' in (name.upper() for name in USERNAMES):
...
Alternatively:
if 'MICHAEL89' in map(str.upper, USERNAMES):
...
Or, yes, you can make a custom method.
edited Sep 2 '10 at 14:09
answered Sep 2 '10 at 13:59
nmichaelsnmichaels
36.3k1082114
36.3k1082114
7
if 'CaseFudge'.lower() in [x.lower() for x in list]
– fredley
Sep 2 '10 at 14:00
38
[...]
creates the whole list.(name.upper() for name in USERNAMES)
would create only a generator and one needed string at a time - massive memory savings if you're doing this operation a lot. (even more savings, if you simply create a list of lowercase usernames that you reuse for checking every time)
– viraptor
Sep 2 '10 at 14:06
2
Prefer to lower all keys when building the dict, for performance reasons.
– Ryan
May 1 '13 at 6:27
if [x.lower() for x in list] is a list comprehension, is (name.upper() for name in USERNAMES) a tuple comprehension? Or does it have another name?
– otocan
Apr 19 '18 at 8:48
1
@otocan It's a generator expression.
– nmichaels
Apr 19 '18 at 13:13
|
show 1 more comment
7
if 'CaseFudge'.lower() in [x.lower() for x in list]
– fredley
Sep 2 '10 at 14:00
38
[...]
creates the whole list.(name.upper() for name in USERNAMES)
would create only a generator and one needed string at a time - massive memory savings if you're doing this operation a lot. (even more savings, if you simply create a list of lowercase usernames that you reuse for checking every time)
– viraptor
Sep 2 '10 at 14:06
2
Prefer to lower all keys when building the dict, for performance reasons.
– Ryan
May 1 '13 at 6:27
if [x.lower() for x in list] is a list comprehension, is (name.upper() for name in USERNAMES) a tuple comprehension? Or does it have another name?
– otocan
Apr 19 '18 at 8:48
1
@otocan It's a generator expression.
– nmichaels
Apr 19 '18 at 13:13
7
7
if 'CaseFudge'.lower() in [x.lower() for x in list]
– fredley
Sep 2 '10 at 14:00
if 'CaseFudge'.lower() in [x.lower() for x in list]
– fredley
Sep 2 '10 at 14:00
38
38
[...]
creates the whole list. (name.upper() for name in USERNAMES)
would create only a generator and one needed string at a time - massive memory savings if you're doing this operation a lot. (even more savings, if you simply create a list of lowercase usernames that you reuse for checking every time)– viraptor
Sep 2 '10 at 14:06
[...]
creates the whole list. (name.upper() for name in USERNAMES)
would create only a generator and one needed string at a time - massive memory savings if you're doing this operation a lot. (even more savings, if you simply create a list of lowercase usernames that you reuse for checking every time)– viraptor
Sep 2 '10 at 14:06
2
2
Prefer to lower all keys when building the dict, for performance reasons.
– Ryan
May 1 '13 at 6:27
Prefer to lower all keys when building the dict, for performance reasons.
– Ryan
May 1 '13 at 6:27
if [x.lower() for x in list] is a list comprehension, is (name.upper() for name in USERNAMES) a tuple comprehension? Or does it have another name?
– otocan
Apr 19 '18 at 8:48
if [x.lower() for x in list] is a list comprehension, is (name.upper() for name in USERNAMES) a tuple comprehension? Or does it have another name?
– otocan
Apr 19 '18 at 8:48
1
1
@otocan It's a generator expression.
– nmichaels
Apr 19 '18 at 13:13
@otocan It's a generator expression.
– nmichaels
Apr 19 '18 at 13:13
|
show 1 more comment
I would make a wrapper so you can be non-invasive. Minimally, for example...:
class CaseInsensitively(object):
def __init__(self, s):
self.__s = s.lower()
def __hash__(self):
return hash(self.__s)
def __eq__(self, other):
# ensure proper comparison between instances of this class
try:
other = other.__s
except (TypeError, AttributeError):
try:
other = other.lower()
except:
pass
return self.__s == other
Now, if CaseInsensitively('MICHAEL89') in whatever:
should behave as required (whether the right-hand side is a list, dict, or set). (It may require more effort to achieve similar results for string inclusion, avoid warnings in some cases involving unicode
, etc).
3
that doesn't work for dict try if CaseInsensitively('MICHAEL89') in {'Michael89':True}:print "found"
– Xavier Combelle
Sep 2 '10 at 14:56
2
Xavier: You would needCaseInsensitively('MICHAEL89') in {CaseInsensitively('Michael89'):True}
for that to work, which probably doesn't fall under "behave as required".
– Gabe
Sep 2 '10 at 15:07
So much for there being only 1 obvious way to do it. This feels heavy unless it's going to be used a lot. That said, it's very smooth.
– nmichaels
Sep 2 '10 at 17:56
1
@Nathon, it seems to me that having to invasively alter the container is the "feels heavy" operation. A completely non-invasive wrapper: how much "lighter" than this could one get?! Not much;-). @Xavier, RHS's that are dicts or sets with mixed-case keys/items need their own non-invasive wrappers (part of the shortetc.
and "require more effort" parts of my answer;-).
– Alex Martelli
Sep 2 '10 at 18:14
My definition of heavy involves writing quite a bit of code to make something that will only be used once, where a less robust but much shorter version would do. If this is going to be used more than once, it's perfectly sensible.
– nmichaels
Sep 2 '10 at 18:35
add a comment |
I would make a wrapper so you can be non-invasive. Minimally, for example...:
class CaseInsensitively(object):
def __init__(self, s):
self.__s = s.lower()
def __hash__(self):
return hash(self.__s)
def __eq__(self, other):
# ensure proper comparison between instances of this class
try:
other = other.__s
except (TypeError, AttributeError):
try:
other = other.lower()
except:
pass
return self.__s == other
Now, if CaseInsensitively('MICHAEL89') in whatever:
should behave as required (whether the right-hand side is a list, dict, or set). (It may require more effort to achieve similar results for string inclusion, avoid warnings in some cases involving unicode
, etc).
3
that doesn't work for dict try if CaseInsensitively('MICHAEL89') in {'Michael89':True}:print "found"
– Xavier Combelle
Sep 2 '10 at 14:56
2
Xavier: You would needCaseInsensitively('MICHAEL89') in {CaseInsensitively('Michael89'):True}
for that to work, which probably doesn't fall under "behave as required".
– Gabe
Sep 2 '10 at 15:07
So much for there being only 1 obvious way to do it. This feels heavy unless it's going to be used a lot. That said, it's very smooth.
– nmichaels
Sep 2 '10 at 17:56
1
@Nathon, it seems to me that having to invasively alter the container is the "feels heavy" operation. A completely non-invasive wrapper: how much "lighter" than this could one get?! Not much;-). @Xavier, RHS's that are dicts or sets with mixed-case keys/items need their own non-invasive wrappers (part of the shortetc.
and "require more effort" parts of my answer;-).
– Alex Martelli
Sep 2 '10 at 18:14
My definition of heavy involves writing quite a bit of code to make something that will only be used once, where a less robust but much shorter version would do. If this is going to be used more than once, it's perfectly sensible.
– nmichaels
Sep 2 '10 at 18:35
add a comment |
I would make a wrapper so you can be non-invasive. Minimally, for example...:
class CaseInsensitively(object):
def __init__(self, s):
self.__s = s.lower()
def __hash__(self):
return hash(self.__s)
def __eq__(self, other):
# ensure proper comparison between instances of this class
try:
other = other.__s
except (TypeError, AttributeError):
try:
other = other.lower()
except:
pass
return self.__s == other
Now, if CaseInsensitively('MICHAEL89') in whatever:
should behave as required (whether the right-hand side is a list, dict, or set). (It may require more effort to achieve similar results for string inclusion, avoid warnings in some cases involving unicode
, etc).
I would make a wrapper so you can be non-invasive. Minimally, for example...:
class CaseInsensitively(object):
def __init__(self, s):
self.__s = s.lower()
def __hash__(self):
return hash(self.__s)
def __eq__(self, other):
# ensure proper comparison between instances of this class
try:
other = other.__s
except (TypeError, AttributeError):
try:
other = other.lower()
except:
pass
return self.__s == other
Now, if CaseInsensitively('MICHAEL89') in whatever:
should behave as required (whether the right-hand side is a list, dict, or set). (It may require more effort to achieve similar results for string inclusion, avoid warnings in some cases involving unicode
, etc).
edited Mar 7 '14 at 12:13
Venkatesh Bachu
1,3151126
1,3151126
answered Sep 2 '10 at 14:45
Alex MartelliAlex Martelli
620k12710341278
620k12710341278
3
that doesn't work for dict try if CaseInsensitively('MICHAEL89') in {'Michael89':True}:print "found"
– Xavier Combelle
Sep 2 '10 at 14:56
2
Xavier: You would needCaseInsensitively('MICHAEL89') in {CaseInsensitively('Michael89'):True}
for that to work, which probably doesn't fall under "behave as required".
– Gabe
Sep 2 '10 at 15:07
So much for there being only 1 obvious way to do it. This feels heavy unless it's going to be used a lot. That said, it's very smooth.
– nmichaels
Sep 2 '10 at 17:56
1
@Nathon, it seems to me that having to invasively alter the container is the "feels heavy" operation. A completely non-invasive wrapper: how much "lighter" than this could one get?! Not much;-). @Xavier, RHS's that are dicts or sets with mixed-case keys/items need their own non-invasive wrappers (part of the shortetc.
and "require more effort" parts of my answer;-).
– Alex Martelli
Sep 2 '10 at 18:14
My definition of heavy involves writing quite a bit of code to make something that will only be used once, where a less robust but much shorter version would do. If this is going to be used more than once, it's perfectly sensible.
– nmichaels
Sep 2 '10 at 18:35
add a comment |
3
that doesn't work for dict try if CaseInsensitively('MICHAEL89') in {'Michael89':True}:print "found"
– Xavier Combelle
Sep 2 '10 at 14:56
2
Xavier: You would needCaseInsensitively('MICHAEL89') in {CaseInsensitively('Michael89'):True}
for that to work, which probably doesn't fall under "behave as required".
– Gabe
Sep 2 '10 at 15:07
So much for there being only 1 obvious way to do it. This feels heavy unless it's going to be used a lot. That said, it's very smooth.
– nmichaels
Sep 2 '10 at 17:56
1
@Nathon, it seems to me that having to invasively alter the container is the "feels heavy" operation. A completely non-invasive wrapper: how much "lighter" than this could one get?! Not much;-). @Xavier, RHS's that are dicts or sets with mixed-case keys/items need their own non-invasive wrappers (part of the shortetc.
and "require more effort" parts of my answer;-).
– Alex Martelli
Sep 2 '10 at 18:14
My definition of heavy involves writing quite a bit of code to make something that will only be used once, where a less robust but much shorter version would do. If this is going to be used more than once, it's perfectly sensible.
– nmichaels
Sep 2 '10 at 18:35
3
3
that doesn't work for dict try if CaseInsensitively('MICHAEL89') in {'Michael89':True}:print "found"
– Xavier Combelle
Sep 2 '10 at 14:56
that doesn't work for dict try if CaseInsensitively('MICHAEL89') in {'Michael89':True}:print "found"
– Xavier Combelle
Sep 2 '10 at 14:56
2
2
Xavier: You would need
CaseInsensitively('MICHAEL89') in {CaseInsensitively('Michael89'):True}
for that to work, which probably doesn't fall under "behave as required".– Gabe
Sep 2 '10 at 15:07
Xavier: You would need
CaseInsensitively('MICHAEL89') in {CaseInsensitively('Michael89'):True}
for that to work, which probably doesn't fall under "behave as required".– Gabe
Sep 2 '10 at 15:07
So much for there being only 1 obvious way to do it. This feels heavy unless it's going to be used a lot. That said, it's very smooth.
– nmichaels
Sep 2 '10 at 17:56
So much for there being only 1 obvious way to do it. This feels heavy unless it's going to be used a lot. That said, it's very smooth.
– nmichaels
Sep 2 '10 at 17:56
1
1
@Nathon, it seems to me that having to invasively alter the container is the "feels heavy" operation. A completely non-invasive wrapper: how much "lighter" than this could one get?! Not much;-). @Xavier, RHS's that are dicts or sets with mixed-case keys/items need their own non-invasive wrappers (part of the short
etc.
and "require more effort" parts of my answer;-).– Alex Martelli
Sep 2 '10 at 18:14
@Nathon, it seems to me that having to invasively alter the container is the "feels heavy" operation. A completely non-invasive wrapper: how much "lighter" than this could one get?! Not much;-). @Xavier, RHS's that are dicts or sets with mixed-case keys/items need their own non-invasive wrappers (part of the short
etc.
and "require more effort" parts of my answer;-).– Alex Martelli
Sep 2 '10 at 18:14
My definition of heavy involves writing quite a bit of code to make something that will only be used once, where a less robust but much shorter version would do. If this is going to be used more than once, it's perfectly sensible.
– nmichaels
Sep 2 '10 at 18:35
My definition of heavy involves writing quite a bit of code to make something that will only be used once, where a less robust but much shorter version would do. If this is going to be used more than once, it's perfectly sensible.
– nmichaels
Sep 2 '10 at 18:35
add a comment |
Usually (in oop at least) you shape your object to behave the way you want. name in USERNAMES
is not case insensitive, so USERNAMES
needs to change:
class NameList(object):
def __init__(self, names):
self.names = names
def __contains__(self, name): # implements `in`
return name.lower() in (n.lower() for n in self.names)
def add(self, name):
self.names.append(name)
# now this works
usernames = NameList(USERNAMES)
print someone in usernames
The great thing about this is that it opens the path for many improvements, without having to change any code outside the class. For example, you could change the self.names
to a set for faster lookups, or compute the (n.lower() for n in self.names)
only once and store it on the class and so on ...
add a comment |
Usually (in oop at least) you shape your object to behave the way you want. name in USERNAMES
is not case insensitive, so USERNAMES
needs to change:
class NameList(object):
def __init__(self, names):
self.names = names
def __contains__(self, name): # implements `in`
return name.lower() in (n.lower() for n in self.names)
def add(self, name):
self.names.append(name)
# now this works
usernames = NameList(USERNAMES)
print someone in usernames
The great thing about this is that it opens the path for many improvements, without having to change any code outside the class. For example, you could change the self.names
to a set for faster lookups, or compute the (n.lower() for n in self.names)
only once and store it on the class and so on ...
add a comment |
Usually (in oop at least) you shape your object to behave the way you want. name in USERNAMES
is not case insensitive, so USERNAMES
needs to change:
class NameList(object):
def __init__(self, names):
self.names = names
def __contains__(self, name): # implements `in`
return name.lower() in (n.lower() for n in self.names)
def add(self, name):
self.names.append(name)
# now this works
usernames = NameList(USERNAMES)
print someone in usernames
The great thing about this is that it opens the path for many improvements, without having to change any code outside the class. For example, you could change the self.names
to a set for faster lookups, or compute the (n.lower() for n in self.names)
only once and store it on the class and so on ...
Usually (in oop at least) you shape your object to behave the way you want. name in USERNAMES
is not case insensitive, so USERNAMES
needs to change:
class NameList(object):
def __init__(self, names):
self.names = names
def __contains__(self, name): # implements `in`
return name.lower() in (n.lower() for n in self.names)
def add(self, name):
self.names.append(name)
# now this works
usernames = NameList(USERNAMES)
print someone in usernames
The great thing about this is that it opens the path for many improvements, without having to change any code outside the class. For example, you could change the self.names
to a set for faster lookups, or compute the (n.lower() for n in self.names)
only once and store it on the class and so on ...
answered Sep 2 '10 at 15:31
Jochen RitzelJochen Ritzel
76.1k21154164
76.1k21154164
add a comment |
add a comment |
I think you have to write some extra code. For example:
if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES):
...
In this case we are forming a new list with all entries in USERNAMES
converted to upper case and then comparing against this new list.
Update
As @viraptor says, it is even better to use a generator instead of map
. See @Nathon's answer.
Or you could useitertools
functionimap
. It's much faster than a generator but accomplishes the same goal.
– wheaties
Sep 2 '10 at 14:24
add a comment |
I think you have to write some extra code. For example:
if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES):
...
In this case we are forming a new list with all entries in USERNAMES
converted to upper case and then comparing against this new list.
Update
As @viraptor says, it is even better to use a generator instead of map
. See @Nathon's answer.
Or you could useitertools
functionimap
. It's much faster than a generator but accomplishes the same goal.
– wheaties
Sep 2 '10 at 14:24
add a comment |
I think you have to write some extra code. For example:
if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES):
...
In this case we are forming a new list with all entries in USERNAMES
converted to upper case and then comparing against this new list.
Update
As @viraptor says, it is even better to use a generator instead of map
. See @Nathon's answer.
I think you have to write some extra code. For example:
if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES):
...
In this case we are forming a new list with all entries in USERNAMES
converted to upper case and then comparing against this new list.
Update
As @viraptor says, it is even better to use a generator instead of map
. See @Nathon's answer.
edited May 23 '17 at 12:10
Community♦
11
11
answered Sep 2 '10 at 14:00
Manoj GovindanManoj Govindan
48.3k19109123
48.3k19109123
Or you could useitertools
functionimap
. It's much faster than a generator but accomplishes the same goal.
– wheaties
Sep 2 '10 at 14:24
add a comment |
Or you could useitertools
functionimap
. It's much faster than a generator but accomplishes the same goal.
– wheaties
Sep 2 '10 at 14:24
Or you could use
itertools
function imap
. It's much faster than a generator but accomplishes the same goal.– wheaties
Sep 2 '10 at 14:24
Or you could use
itertools
function imap
. It's much faster than a generator but accomplishes the same goal.– wheaties
Sep 2 '10 at 14:24
add a comment |
You could do
matcher = re.compile('MICHAEL89', re.IGNORECASE)
filter(matcher.match, USERNAMES)
Update: played around a bit and am thinking you could get a better short-circuit type approach using
matcher = re.compile('MICHAEL89', re.IGNORECASE)
if any( ifilter( matcher.match, USERNAMES ) ):
#your code here
The ifilter
function is from itertools, one of my favorite modules within Python. It's faster than a generator but only creates the next item of the list when called upon.
Just to add, the pattern might need to be escaped, since it might contain characters like ".","?", which has specail meaning in regular expression patterns. use re.escape(raw_string) to do it
– Iching Chang
Jan 8 '17 at 23:29
add a comment |
You could do
matcher = re.compile('MICHAEL89', re.IGNORECASE)
filter(matcher.match, USERNAMES)
Update: played around a bit and am thinking you could get a better short-circuit type approach using
matcher = re.compile('MICHAEL89', re.IGNORECASE)
if any( ifilter( matcher.match, USERNAMES ) ):
#your code here
The ifilter
function is from itertools, one of my favorite modules within Python. It's faster than a generator but only creates the next item of the list when called upon.
Just to add, the pattern might need to be escaped, since it might contain characters like ".","?", which has specail meaning in regular expression patterns. use re.escape(raw_string) to do it
– Iching Chang
Jan 8 '17 at 23:29
add a comment |
You could do
matcher = re.compile('MICHAEL89', re.IGNORECASE)
filter(matcher.match, USERNAMES)
Update: played around a bit and am thinking you could get a better short-circuit type approach using
matcher = re.compile('MICHAEL89', re.IGNORECASE)
if any( ifilter( matcher.match, USERNAMES ) ):
#your code here
The ifilter
function is from itertools, one of my favorite modules within Python. It's faster than a generator but only creates the next item of the list when called upon.
You could do
matcher = re.compile('MICHAEL89', re.IGNORECASE)
filter(matcher.match, USERNAMES)
Update: played around a bit and am thinking you could get a better short-circuit type approach using
matcher = re.compile('MICHAEL89', re.IGNORECASE)
if any( ifilter( matcher.match, USERNAMES ) ):
#your code here
The ifilter
function is from itertools, one of my favorite modules within Python. It's faster than a generator but only creates the next item of the list when called upon.
edited Sep 2 '10 at 15:15
answered Sep 2 '10 at 14:03
wheatieswheaties
29.9k972121
29.9k972121
Just to add, the pattern might need to be escaped, since it might contain characters like ".","?", which has specail meaning in regular expression patterns. use re.escape(raw_string) to do it
– Iching Chang
Jan 8 '17 at 23:29
add a comment |
Just to add, the pattern might need to be escaped, since it might contain characters like ".","?", which has specail meaning in regular expression patterns. use re.escape(raw_string) to do it
– Iching Chang
Jan 8 '17 at 23:29
Just to add, the pattern might need to be escaped, since it might contain characters like ".","?", which has specail meaning in regular expression patterns. use re.escape(raw_string) to do it
– Iching Chang
Jan 8 '17 at 23:29
Just to add, the pattern might need to be escaped, since it might contain characters like ".","?", which has specail meaning in regular expression patterns. use re.escape(raw_string) to do it
– Iching Chang
Jan 8 '17 at 23:29
add a comment |
str.casefold
is recommended for case-insensitive string matching. @nmichaels's solution can trivially be adapted.
Use either:
if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):
Or:
if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):
As per the docs:
Casefolding is similar to lowercasing but more aggressive because it
is intended to remove all case distinctions in a string. For example,
the German lowercase letter 'ß' is equivalent to "ss". Since it is
already lowercase,lower()
would do nothing to 'ß';casefold()
converts it to "ss".
add a comment |
str.casefold
is recommended for case-insensitive string matching. @nmichaels's solution can trivially be adapted.
Use either:
if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):
Or:
if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):
As per the docs:
Casefolding is similar to lowercasing but more aggressive because it
is intended to remove all case distinctions in a string. For example,
the German lowercase letter 'ß' is equivalent to "ss". Since it is
already lowercase,lower()
would do nothing to 'ß';casefold()
converts it to "ss".
add a comment |
str.casefold
is recommended for case-insensitive string matching. @nmichaels's solution can trivially be adapted.
Use either:
if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):
Or:
if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):
As per the docs:
Casefolding is similar to lowercasing but more aggressive because it
is intended to remove all case distinctions in a string. For example,
the German lowercase letter 'ß' is equivalent to "ss". Since it is
already lowercase,lower()
would do nothing to 'ß';casefold()
converts it to "ss".
str.casefold
is recommended for case-insensitive string matching. @nmichaels's solution can trivially be adapted.
Use either:
if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):
Or:
if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):
As per the docs:
Casefolding is similar to lowercasing but more aggressive because it
is intended to remove all case distinctions in a string. For example,
the German lowercase letter 'ß' is equivalent to "ss". Since it is
already lowercase,lower()
would do nothing to 'ß';casefold()
converts it to "ss".
answered Aug 10 '18 at 8:36
jppjpp
93.5k2054104
93.5k2054104
add a comment |
add a comment |
Here's one way:
if string1.lower() in string2.lower():
...
For this to work, both string1
and string2
objects must be of type string
.
4
AttributeError: 'list' object has no attribute 'lower'
– Jeff
Oct 13 '17 at 12:26
@Jeff that's because one of your elements is a list, and both objects should be a string. Which object is a list?
– User
yesterday
I would up vote you, but I cannot unless you edit your answer. You are absolutely right.
– Jeff
yesterday
@Jeff I added clarification.
– User
yesterday
add a comment |
Here's one way:
if string1.lower() in string2.lower():
...
For this to work, both string1
and string2
objects must be of type string
.
4
AttributeError: 'list' object has no attribute 'lower'
– Jeff
Oct 13 '17 at 12:26
@Jeff that's because one of your elements is a list, and both objects should be a string. Which object is a list?
– User
yesterday
I would up vote you, but I cannot unless you edit your answer. You are absolutely right.
– Jeff
yesterday
@Jeff I added clarification.
– User
yesterday
add a comment |
Here's one way:
if string1.lower() in string2.lower():
...
For this to work, both string1
and string2
objects must be of type string
.
Here's one way:
if string1.lower() in string2.lower():
...
For this to work, both string1
and string2
objects must be of type string
.
edited yesterday
answered Aug 1 '14 at 21:01
UserUser
7,5292579137
7,5292579137
4
AttributeError: 'list' object has no attribute 'lower'
– Jeff
Oct 13 '17 at 12:26
@Jeff that's because one of your elements is a list, and both objects should be a string. Which object is a list?
– User
yesterday
I would up vote you, but I cannot unless you edit your answer. You are absolutely right.
– Jeff
yesterday
@Jeff I added clarification.
– User
yesterday
add a comment |
4
AttributeError: 'list' object has no attribute 'lower'
– Jeff
Oct 13 '17 at 12:26
@Jeff that's because one of your elements is a list, and both objects should be a string. Which object is a list?
– User
yesterday
I would up vote you, but I cannot unless you edit your answer. You are absolutely right.
– Jeff
yesterday
@Jeff I added clarification.
– User
yesterday
4
4
AttributeError: 'list' object has no attribute 'lower'
– Jeff
Oct 13 '17 at 12:26
AttributeError: 'list' object has no attribute 'lower'
– Jeff
Oct 13 '17 at 12:26
@Jeff that's because one of your elements is a list, and both objects should be a string. Which object is a list?
– User
yesterday
@Jeff that's because one of your elements is a list, and both objects should be a string. Which object is a list?
– User
yesterday
I would up vote you, but I cannot unless you edit your answer. You are absolutely right.
– Jeff
yesterday
I would up vote you, but I cannot unless you edit your answer. You are absolutely right.
– Jeff
yesterday
@Jeff I added clarification.
– User
yesterday
@Jeff I added clarification.
– User
yesterday
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f3627784%2fcase-insensitive-in-python%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown