python - على - منتديات بايثون




كيف أقوم بإجراء مقارنة سلسلة غير حساسة لحالة الأحرف؟ (7)

إذا كان لديك قوائم تحتوي على سلاسل وترغب في المقارنة بين السلاسل في قائمة مختلفة غير حساسة لحالة الأحرف. هنا هو الحل الخاص بي.

list1 = map(lambda each:each.lower(), list1)
list2 = map(lambda each:each.lower(), list2)

بعد القيام بذلك ، يمكنك إجراء مقارنة سلسلة easly.

كيف يمكنني أن أفعل مقارنة سلسلة غير حساسة في بايثون؟

أرغب في تغليف مقارنة السلاسل المنتظمة بسلسلة مستودع باستخدام طريقة بسيطة للغاية وبايثونية. وأود أيضا أن يكون لديك القدرة على البحث عن القيم في طريقة تجزئتها السلاسل باستخدام خيوط الثعبان العادية.


النهج المعتاد هو أن تستخدم الأحرف الكبيرة أو الأحرف الصغيرة في عمليات البحث والمقارنات. فمثلا:

>>> "hello".upper() == "HELLO".upper()
True
>>> 

بافتراض سلاسل ASCII:

string1 = 'Hello'
string2 = 'hello'

if string1.lower() == string2.lower():
    print "The strings are the same (case insensitive)"
else:
    print "The strings are not the same (case insensitive)"

رأيت هذا الحل here باستخدام regex .

import re
if re.search('mandy', 'Mandy Pande', re.IGNORECASE):
# is True

وهو يعمل بشكل جيد مع اللكنات

In [42]: if re.search("ê","ê", re.IGNORECASE):
....:        print(1)
....:
1

ومع ذلك ، فإنه لا يعمل مع أحرف unicode لحساسية الأحرف. نشكركم علىRhymoid للإشارة إلى أن ما أفهمه هو أنه يحتاج إلى الرمز الدقيق ، حتى تكون الحالة صحيحة. الإخراج كالتالي:

In [36]: "ß".lower()
Out[36]: 'ß'
In [37]: "ß".upper()
Out[37]: 'SS'
In [38]: "ß".upper().lower()
Out[38]: 'ss'
In [39]: if re.search("ß","ßß", re.IGNORECASE):
....:        print(1)
....:
1
In [40]: if re.search("SS","ßß", re.IGNORECASE):
....:        print(1)
....:
In [41]: if re.search("ß","SS", re.IGNORECASE):
....:        print(1)
....:

ماذا عن التحويل إلى أحرف صغيرة أولاً؟ يمكنك استخدام string.lower() .


يبدو أن مقارنة السلسلة بطريقة غير حساسة تبدو كشيء بسيط ، ولكنها ليست كذلك. سأستخدم بايثون 3 ، لأن بيثون 2 غير متطورة هنا.

أول شيء أن نلاحظ أن تحويلات إزالة الحالة في Unicode ليست تافهة. يوجد نص له text.lower() != text.upper().lower() ، مثل "ß" :

"ß".lower()
#>>> 'ß'

"ß".upper().lower()
#>>> 'ss'

ولكن دعنا نقول أنك تريد مقارنة "BUSSE" و "Buße" . هيك ، ربما تريد أيضا مقارنة "BUSSE" و "BUẞE" قدم المساواة - هذا هو شكل رأس المال الجديد. الطريقة الموصى بها هي استخدام casefold :

help(str.casefold)
#>>> Help on method_descriptor:
#>>>
#>>> casefold(...)
#>>>     S.casefold() -> str
#>>>     
#>>>     Return a version of S suitable for caseless comparisons.
#>>>

لا تستخدم فقط lower . إذا كان casefold غير متوفر ، فإن القيام .upper().lower() يساعد (ولكن إلى حد ما).

ثم يجب عليك أن تنظر في اللهجات. إذا كان عارض الخطوط الخاص بك جيدًا ، فمن المحتمل أن تفكر "ê" == "ê" - ولكنها لا:

"ê" == "ê"
#>>> False

هذا لأنهم في الواقع

import unicodedata

[unicodedata.name(char) for char in "ê"]
#>>> ['LATIN SMALL LETTER E WITH CIRCUMFLEX']

[unicodedata.name(char) for char in "ê"]
#>>> ['LATIN SMALL LETTER E', 'COMBINING CIRCUMFLEX ACCENT']

أبسط طريقة للتعامل مع هذا هو unicodedata.normalize . ربما تريد استخدام تطبيع NFKD ، ولكن لا تتردد في التحقق من الوثائق. ثم واحد يفعل

unicodedata.normalize("NFKD", "ê") == unicodedata.normalize("NFKD", "ê")
#>>> True

لإنهاء ، هنا يتم التعبير عن هذا في وظائف:

import unicodedata

def normalize_caseless(text):
    return unicodedata.normalize("NFKD", text.casefold())

def caseless_equal(left, right):
    return normalize_caseless(left) == normalize_caseless(right)

def insenStringCompare(s1, s2):
    """ Method that takes two strings and returns True or False, based
        on if they are equal, regardless of case."""
    try:
        return s1.lower() == s2.lower()
    except AttributeError:
        print "Please only pass strings into this method."
        print "You passed a %s and %s" % (s1.__class__, s2.__class__)




case-insensitive