Case insensitive 'in' - Python












115














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!










share|improve this question





























    115














    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!










    share|improve this question



























      115












      115








      115


      20





      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!










      share|improve this question















      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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Mar 18 '14 at 19:11









      Connor

      51.1k22113128




      51.1k22113128










      asked Sep 2 '10 at 13:56









      RadiantHexRadiantHex

      9,62935122223




      9,62935122223
























          7 Answers
          7






          active

          oldest

          votes


















          140














          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.






          share|improve this answer



















          • 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



















          16














          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).






          share|improve this answer



















          • 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 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








          • 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










          • 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



















          9














          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 ...






          share|improve this answer





























            6














            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.






            share|improve this answer























            • 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



















            4














            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.






            share|improve this answer























            • 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



















            3














            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".







            share|improve this answer





























              3














              Here's one way:



              if string1.lower() in string2.lower(): 
              ...


              For this to work, both string1 and string2 objects must be of type string.






              share|improve this answer



















              • 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











              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
              });


              }
              });














              draft saved

              draft discarded


















              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









              140














              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.






              share|improve this answer



















              • 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
















              140














              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.






              share|improve this answer



















              • 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














              140












              140








              140






              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.






              share|improve this answer














              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.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              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














              • 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













              16














              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).






              share|improve this answer



















              • 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 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








              • 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










              • 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
















              16














              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).






              share|improve this answer



















              • 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 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








              • 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










              • 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














              16












              16








              16






              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).






              share|improve this answer














              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).







              share|improve this answer














              share|improve this answer



              share|improve this answer








              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 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








              • 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










              • 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




                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 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








              • 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










              • 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











              9














              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 ...






              share|improve this answer


























                9














                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 ...






                share|improve this answer
























                  9












                  9








                  9






                  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 ...






                  share|improve this answer












                  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 ...







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Sep 2 '10 at 15:31









                  Jochen RitzelJochen Ritzel

                  76.1k21154164




                  76.1k21154164























                      6














                      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.






                      share|improve this answer























                      • 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
















                      6














                      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.






                      share|improve this answer























                      • 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














                      6












                      6








                      6






                      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.






                      share|improve this 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.







                      share|improve this answer














                      share|improve this answer



                      share|improve this 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 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
















                      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











                      4














                      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.






                      share|improve this answer























                      • 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
















                      4














                      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.






                      share|improve this answer























                      • 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














                      4












                      4








                      4






                      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.






                      share|improve this answer














                      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.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      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


















                      • 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











                      3














                      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".







                      share|improve this answer


























                        3














                        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".







                        share|improve this answer
























                          3












                          3








                          3






                          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".







                          share|improve this answer












                          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".








                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Aug 10 '18 at 8:36









                          jppjpp

                          93.5k2054104




                          93.5k2054104























                              3














                              Here's one way:



                              if string1.lower() in string2.lower(): 
                              ...


                              For this to work, both string1 and string2 objects must be of type string.






                              share|improve this answer



















                              • 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
















                              3














                              Here's one way:



                              if string1.lower() in string2.lower(): 
                              ...


                              For this to work, both string1 and string2 objects must be of type string.






                              share|improve this answer



















                              • 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














                              3












                              3








                              3






                              Here's one way:



                              if string1.lower() in string2.lower(): 
                              ...


                              For this to work, both string1 and string2 objects must be of type string.






                              share|improve this answer














                              Here's one way:



                              if string1.lower() in string2.lower(): 
                              ...


                              For this to work, both string1 and string2 objects must be of type string.







                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              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














                              • 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


















                              draft saved

                              draft discarded




















































                              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.




                              draft saved


                              draft discarded














                              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





















































                              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







                              Popular posts from this blog

                              404 Error Contact Form 7 ajax form submitting

                              How to know if a Active Directory user can login interactively

                              TypeError: fit_transform() missing 1 required positional argument: 'X'