表現を使うのが大好き
if 'MICHAEL89' in USERNAMES:
...
ここで、USERNAMES
はリストです
大文字と小文字を区別しないアイテムを一致させる方法はありますか、またはカスタムメソッドを使用する必要がありますか?このために余分なコードを書く必要があるかどうか疑問に思っています。
みんなありがとう!
if 'MICHAEL89' in (name.upper() for name in USERNAMES):
...
代わりに:
if 'MICHAEL89' in map(str.upper, USERNAMES):
...
または、はい、カスタムメソッドを作成できます。
wrapperを作成するので、非侵襲的になります。最小限、例えば...:
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
これで、if CaseInsensitively('MICHAEL89') in whatever:
は必要に応じて動作するはずです(右側がリスト、辞書、またはセットであるかどうか)。 (文字列を含めるために同様の結果を得るには、さらに労力が必要になる場合があり、unicode
などが関係する場合には警告を回避します)。
通常、(少なくともoopでは)目的の動作をするようにオブジェクトを形作ります。 name in USERNAMES
は大文字と小文字を区別しないため、USERNAMES
は変更する必要があります。
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
これの素晴らしいところは、クラス外のコードを変更することなく、多くの改善への道を開くことです。たとえば、self.names
をセットに変更してルックアップを高速化したり、(n.lower() for n in self.names)
を1回だけ計算してクラスなどに保存したりできます。
余分なコードを書く必要があると思います。例えば:
if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES):
...
この場合、USERNAMES
のすべてのエントリが大文字に変換された新しいリストを作成し、この新しいリストと比較します。
更新
@ viraptor が示すように、map
の代わりにジェネレーターを使用することをお勧めします。 @ Nathon の answer を参照してください。
1つの方法を次に示します。
if string1.lower() in string2.lower():
...
これが機能するには、string1
およびstring2
オブジェクトの両方がstring
型である必要があります。
str.casefold
は、大文字と小文字を区別しない文字列照合に推奨されます。 @ nmichaelsの解 は簡単に適応できます。
次のいずれかを使用します。
if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):
または:
if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):
docs :
ケースフォールディングは小文字化に似ていますが、文字列内のすべての大文字と小文字の区別を削除することを目的としているため、より積極的です。たとえば、ドイツ語の小文字「ß」は「ss」と同等です。既に小文字なので、
lower()
は 'ß'に対して何もしません。casefold()
は「ss」に変換します。
できる
matcher = re.compile('MICHAEL89', re.IGNORECASE)
filter(matcher.match, USERNAMES)
更新:少し遊んで、あなたがより良い短絡型のアプローチを得ることができると考えています
matcher = re.compile('MICHAEL89', re.IGNORECASE)
if any( ifilter( matcher.match, USERNAMES ) ):
#your code here
ifilter
関数は、Pythonで私のお気に入りのモジュールの1つであるitertoolsからのものです。ジェネレータよりも高速ですが、呼び出されたときにリストの次のアイテムのみを作成します。
私の5(間違った)セント
"" .join(['A'])。lower()の 'a'
@jppに完全に同意します。悪い習慣の例として私は続けます:(