Bagaimana saya bisa melakukan perbandingan string case insensitive dengan Python?
Saya ingin merangkum perbandingan string biasa ke string repositori menggunakan cara yang sangat sederhana dan Pythonic. Saya juga ingin memiliki kemampuan untuk mencari nilai-nilai dalam dict hash dengan string menggunakan string python biasa.
python
comparison
case-insensitive
Kozyarchuk
sumber
sumber
Σίσυφος
danΣΊΣΥΦΟΣ
, maka pendekatan Anda gagal, karena mereka seharusnya menjadi kasus yang sama tidak sensitif.'ß'.lower() == 'SS'.lower()
salah.Membandingkan string dengan case case peka tampaknya sepele, tapi tidak. Saya akan menggunakan Python 3, karena Python 2 kurang dikembangkan di sini.
Hal pertama yang perlu diperhatikan adalah konversi penghapusan case di Unicode tidak sepele. Ada teks untuk itu
text.lower() != text.upper().lower()
, seperti"ß"
:Tapi katakanlah Anda ingin membandingkan
"BUSSE"
dan"Buße"
. Heck, Anda mungkin juga ingin membandingkan"BUSSE"
dan"BUẞE"
menyamakan - itulah bentuk modal yang lebih baru. Cara yang disarankan adalah menggunakancasefold
:Jangan hanya digunakan
lower
. Jikacasefold
tidak tersedia, melakukan.upper().lower()
bantuan (tetapi hanya sedikit).Maka Anda harus mempertimbangkan aksen. Jika font renderer Anda bagus, Anda mungkin berpikir
"ê" == "ê"
- tetapi itu tidak:Ini karena aksen pada yang terakhir adalah karakter yang menggabungkan.
Cara paling sederhana untuk mengatasinya adalah
unicodedata.normalize
. Anda mungkin ingin menggunakan normalisasi NFKD , tetapi jangan ragu untuk memeriksa dokumentasinya. Lalu seseorang melakukannyaUntuk menyelesaikan, di sini ini dinyatakan dalam fungsi:
sumber
x.casefold() == y.casefold()
perbandingan case-sensitive (dan, yang lebih penting,x == y
untuk case-sensitive).NFD(toCasefold(NFD(str)))
di kedua sisi dan (D147, kompatibilitas)NFKD(toCasefold(NFKD(toCasefold(NFD(X)))))
di kedua sisi. Ini menyatakan batinNFD
semata-mata untuk menangani karakter aksen Yunani tertentu. Saya kira itu semua tentang kasus tepi.Menggunakan Python 2, memanggil
.lower()
setiap string atau objek Unicode ...... akan bekerja sebagian besar waktu, tetapi memang tidak bekerja dalam situasi yang dijelaskan @tchrist .
Asumsikan kita memiliki file bernama
unicode.txt
mengandung dua stringΣίσυφος
danΣΊΣΥΦΟΣ
. Dengan Python 2:Karakter Σ memiliki dua bentuk huruf kecil, ς dan σ, dan
.lower()
tidak akan membantu membandingkannya dengan huruf besar-kecil.Namun, pada Python 3, ketiga formulir akan memutuskan untuk ς, dan memanggil lebih rendah () pada kedua string akan bekerja dengan benar:
Jadi jika Anda peduli tentang kasus tepi seperti tiga sigma dalam bahasa Yunani, gunakan Python 3.
(Untuk referensi, Python 2.7.3 dan Python 3.3.0b1 ditunjukkan dalam cetakan juru bahasa di atas.)
sumber
Bagian 3.13 dari standar Unicode mendefinisikan algoritma untuk pencocokan tanpa casing.
X.casefold() == Y.casefold()
dalam Python 3 mengimplementasikan "standar pencocokan kosong" (D144).Casefolding tidak mempertahankan normalisasi string dalam semua kasus dan oleh karena itu normalisasi perlu dilakukan (
'å'
vs'å'
). D145 memperkenalkan "pencocokan santai kanonik":NFD()
dipanggil dua kali untuk kasus tepi yang sangat jarang yang melibatkan karakter U + 0345.Contoh:
Ada juga kompatibilitas pencocokan Caseless (D146) untuk kasus-kasus seperti
'㎒'
(U + 3392) dan "pengidentifikasi pencocokan Caseless" untuk menyederhanakan dan mengoptimalkan pencocokan Caseless pengidentifikasi .sumber
casefold()
fungsi tersebut tidak mengimplementasikan perlakuan kasus khusus huruf besar I dan huruf besar bertitik I seperti yang dijelaskan dalam Case Folding Properties . Oleh karena itu, perbandingannya mungkin gagal untuk kata-kata dari bahasa Turki yang berisi surat-surat itu. Misalnya,canonical_caseless('LİMANI') == canonical_caseless('limanı')
harus kembaliTrue
, tetapi kembaliFalse
. Saat ini, satu-satunya cara untuk menangani hal ini dengan Python adalah dengan menulis bungkus casefold atau menggunakan pustaka Unicode eksternal, seperti PyICU.Saya melihat solusi ini di sini menggunakan regex .
Ini bekerja dengan baik dengan aksen
Namun, itu tidak berfungsi dengan karakter unicode case-insensitive. Terima kasih @Rhoidoid untuk menunjukkan bahwa karena pemahaman saya adalah bahwa ia membutuhkan simbol yang tepat, agar kasus ini benar. Outputnya adalah sebagai berikut:
sumber
ß
tidak ditemukan dalamSS
dengan case-insensitive pencarian bukti bahwa hal itu tidak bekerja kerja dengan karakter Unicode sama sekali .Pendekatan yang biasa digunakan adalah huruf besar string atau huruf kecil untuk pencarian dan perbandingan. Sebagai contoh:
sumber
Bagaimana kalau mengkonversi ke huruf kecil dulu? Anda dapat menggunakan
string.lower()
.sumber
Σίσυφος
danΣΊΣΥΦΟΣ
tidak akan menguji yang setara, tetapi harus.sumber
Yang harus Anda lakukan adalah mengubah dua string menjadi huruf kecil (semua huruf menjadi huruf kecil) dan kemudian membandingkannya (dengan asumsi string adalah string ASCII).
Sebagai contoh:
sumber
Ini adalah regex lain yang telah saya pelajari untuk sukai / benci selama seminggu terakhir jadi biasanya diimpor sebagai (dalam hal ini ya) sesuatu yang mencerminkan bagaimana perasaan saya! buat fungsi normal .... minta input, lalu gunakan .... something = re.compile (r'foo * | spam * ', yes.I) ...... re.I (yes.I di bawah) sama dengan IGNORECASE tetapi Anda tidak dapat membuat banyak kesalahan saat menuliskannya!
Anda kemudian mencari pesan Anda menggunakan regex tetapi jujur itu harus beberapa halaman sendiri, tetapi intinya adalah bahwa foo atau spam disalurkan bersama dan case diabaikan. Kemudian jika salah satu ditemukan maka Lost_n_found akan menampilkan salah satunya. jika tidak ada yang hilang maka ditemukan sama dengan Tidak ada. Jika tidak sama dengan tidak mengembalikan user_input dalam huruf kecil menggunakan "return lost_n_found.lower ()"
Ini memungkinkan Anda untuk lebih mudah mencocokkan apa pun yang peka terhadap huruf besar-kecil. Terakhir (NCS) berarti "tidak ada yang peduli dengan serius ...!" atau tidak case sensitif .... mana
jika ada yang punya pertanyaan buat saya tentang ini ..
sumber