Saya jatuh ke dalam masalah yang mengejutkan.
Saya memuat file teks dalam aplikasi saya dan saya memiliki beberapa logika yang membandingkan nilai yang memiliki µ.
Dan saya menyadari bahwa meskipun teksnya sama, nilai pembandingnya salah.
Console.WriteLine("μ".Equals("µ")); // returns false
Console.WriteLine("µ".Equals("µ")); // return true
Di baris berikutnya karakter µ disalin.
Namun, ini mungkin bukan satu-satunya karakter yang seperti ini.
Apakah ada cara di C # untuk membandingkan karakter yang terlihat sama tetapi sebenarnya berbeda?
Jawaban:
Dalam banyak kasus, Anda dapat menormalkan kedua karakter Unicode ke bentuk normalisasi tertentu sebelum membandingkannya, dan keduanya harus bisa cocok. Tentu saja, bentuk normalisasi mana yang perlu Anda gunakan bergantung pada karakter itu sendiri; hanya karena mereka terlihat mirip tidak berarti mereka mewakili karakter yang sama. Anda juga perlu mempertimbangkan apakah itu sesuai untuk kasus penggunaan Anda - lihat komentar Jukka K. Korpela.
Untuk situasi khusus ini, jika Anda merujuk ke tautan dalam jawaban Tony , Anda akan melihat bahwa tabel untuk U + 00B5 mengatakan:
Ini berarti U + 00B5, karakter kedua dalam perbandingan awal Anda, dapat diuraikan menjadi U + 03BC, karakter pertama.
Jadi Anda akan menormalkan karakter menggunakan dekomposisi kompatibilitas penuh, dengan bentuk normalisasi KC atau KD. Inilah contoh singkat yang saya tulis untuk ditunjukkan:
Untuk detail tentang normalisasi Unicode dan bentuk normalisasi yang berbeda, lihat
System.Text.NormalizationForm
dan spesifikasi Unicode .sumber
Karena sangat berbeda simbolnya walaupun terlihat sama, yang pertama adalah huruf yang sebenarnya dan memiliki karakter
code = 956 (0x3BC)
dan yang kedua adalah tanda mikro dan memiliki181 (0xB5)
.Referensi:
Jadi jika Anda ingin membandingkannya dan Anda ingin keduanya sama, Anda perlu menanganinya secara manual, atau mengganti satu karakter dengan karakter lain sebelum dibandingkan. Atau gunakan kode berikut:
Dan Demo
sumber
Keduanya memiliki kode karakter yang berbeda: Lihat ini untuk detail selengkapnya
Dimana, yang pertama adalah:
sumber
Untuk contoh spesifik dari
μ
(mu) danµ
(tanda mikro), yang terakhir memiliki dekomposisi kompatibilitas dengan yang pertama, sehingga Anda dapat menormalkan string menjadiFormKC
atauFormKD
mengubah tanda mikro menjadi mus.Namun, ada banyak set karakter yang mirip tetapi tidak setara dalam bentuk normalisasi Unicode. Misalnya,
A
(Latin),Α
(Yunani), danА
(Sirilik). Situs web Unicode memiliki file confusables.txt dengan daftar ini, dimaksudkan untuk membantu pengembang menjaga dari serangan homograf . Jika perlu, Anda dapat mengurai file ini dan membuat tabel untuk "normalisasi visual" string.sumber
ToUpper
/ToLower
sulit untuk diterapkan. Anda akan perlu untuk memiliki"B".ToLower()
menjadib
dalam bahasa Inggris namunβ
di Yunani danв
di Rusia. Karena itu, hanya Turki (tanpa titiki
) dan beberapa bahasa lain yang memerlukan aturan huruf besar yang berbeda dari default.Cari kedua karakter dalam database Unicode dan lihat perbedaannya .
Salah satunya adalah Huruf kecil Yunani
µ
dan yang lainnya adalah Tanda Mikroµ
.sumber
EDIT Setelah menggabungkan pertanyaan ini dengan Bagaimana membandingkan 'μ' dan 'µ' di C #
Jawaban asli diposting:
EDIT Setelah membaca komentar, ya tidak baik menggunakan metode di atas karena dapat memberikan hasil yang salah untuk beberapa jenis input lainnya, untuk ini kita harus menggunakan normalisasi menggunakan dekomposisi kompatibilitas penuh seperti yang disebutkan di wiki . (Berkat jawaban yang diposting oleh BoltClock )
Keluaran
Saat membaca informasi di Unicode_equivalence saya temukan
Jadi untuk membandingkan kesetaraan kita biasanya menggunakan
FormKC
normalisasi yaitu NFKC atauFormKD
normalisasi NFKD.Saya sedikit penasaran untuk mengetahui lebih banyak tentang semua karakter Unicode jadi saya membuat sampel yang akan mengulang semua karakter Unicode di
UTF-16
dan saya mendapatkan beberapa hasil yang ingin saya diskusikanFormC
danFormD
nilai yang dinormalkan tidak setaraTotal: 12,118
Character (int value): 192-197, 199-207, 209-214, 217-221, 224-253, ..... 44032-55203
FormKC
danFormKD
nilai yang dinormalkan tidak setaraTotal: 12,245
Character (int value): 192-197, 199-207, 209-214, 217-221, 224-228, ..... 44032-55203, 64420-64421, 64432-64433, 64490-64507, 64512-64516, 64612-64617, 64663-64667, 64735-64736, 65153-65164, 65269-65274
FormC
danFormD
nilainya dinormalisasi tidak setara, adaFormKC
danFormKD
nilai yang dinormalisasi juga tidak setara kecuali karakter berikut.Karakter:
901 '΅', 8129 '῁', 8141 '῍', 8142 '῎', 8143 '῏', 8157 '῝', 8158 '῞'
, 8159 '῟', 8173 '῭', 8174 '΅'
FormKC
danFormKD
nilainya dinormalisasi tidak setara, tetapi adaFormC
danFormD
nilai yang dinormalkan setaraTotal: 119
Karakter:
452 'DŽ' 453 'Dž' 454 'dž' 12814 '㈎' 12815 '㈏' 12816 '㈐' 12817 '㈑' 12818 '㈒' 12819 '㈓' 12820 '㈔' 12821 '㈕', 12822 '㈖' 12823 '㈗' 12824 '㈘' 12825 '㈙' 12826 '㈚' 12827 '㈛' 12828 '㈜' 12829 '㈝' 12830 '㈞' 12910 '㉮' 12911 '㉯' 12912 '㉰' 12913 '㉱' 12914 '㉲' 12915 '㉳' 12916 '㉴' 12917 '㉵' 12918 '㉶' 12919 '㉷' 12920 '㉸' 12921 '㉹' 12922 '㉺' 12923 '㉻' 12924 '㉼' 12925 '㉽' 12926 '㉾' 13056 '㌀' 13058 '㌂' 13060 '㌄' 13063 '㌇' 13070 '㌎' 13071 '㌏' 13072 '㌐' 13073 '㌑' 13075 '㌓' 13077 '㌕' 13080 '㌘' 13081 '㌙' 13082 '㌚' 13086 '㌞' 13089 '㌡' 13092 '㌤' 13093 '㌥' 13094 '㌦' 13099 '㌫' 13100 '㌬' 13101 '㌭' 13102 '㌮' 13103 '㌯' 13104 '㌰' 13105 '㌱' 13106 '㌲' 13108 '㌴' 13111 '㌷' 13112 '㌸' 13114 '㌺' 13115 '㌻' 13116 '㌼' 13117 '㌽' 13118 '㌾' 13120 '㍀' 13130 '㍊' 13131 '㍋' 13132 '㍌' 13134 '㍎' 13139 '㍓' 13140 '㍔' 13142 '㍖' .......... ﺋ' 65164 'ﺌ' 65269 'ﻵ' 65270 'ﻶ' 65271 'ﻷ' 65272 'ﻸ' 65273 'ﻹ' 65274'
ArgumentException
jika dicobaTotal:2081
Characters(int value): 55296-57343, 64976-65007, 65534
Tautan ini dapat sangat membantu untuk memahami aturan apa yang mengatur kesetaraan Unicode
sumber
"m".ToUpper().Equals("µ".ToUpper());
dan"M".ToUpper().Equals("µ".ToUpper());
juga benar. Ini mungkin tidak diinginkan.Kemungkinan besar, ada dua kode karakter berbeda yang membuat karakter (terlihat) sama. Meski secara teknis tidak sama, mereka terlihat setara. Lihat tabel karakter dan lihat apakah ada beberapa contoh karakter itu. Atau cetak kode karakter dari dua karakter di kode Anda.
sumber
Anda bertanya "bagaimana membandingkannya" tetapi Anda tidak memberi tahu kami apa yang ingin Anda lakukan.
Setidaknya ada dua cara utama untuk membandingkannya:
Baik Anda membandingkannya secara langsung apa adanya dan keduanya berbeda
Atau Anda menggunakan Unicode Compatibility Normalization jika Anda membutuhkan perbandingan yang menurut Anda cocok.
Mungkin ada masalah karena normalisasi kompatibilitas Unicode akan membuat banyak karakter lain sebanding. Jika Anda hanya ingin kedua karakter ini diperlakukan sama, Anda harus menggulung fungsi normalisasi atau perbandingan Anda sendiri.
Untuk solusi yang lebih spesifik, kami perlu mengetahui masalah spesifik Anda. Dalam konteks apa Anda menemukan masalah ini?
sumber
Jika saya ingin bertele-tele, saya akan mengatakan bahwa pertanyaan Anda tidak masuk akal, tetapi karena kita mendekati natal dan burung-burung bernyanyi, saya akan melanjutkan dengan ini.
Pertama, 2 entitas yang Anda coba bandingkan adalah
glyph
s, mesin terbang adalah bagian dari kumpulan mesin terbang yang disediakan oleh apa yang biasanya dikenal sebagai "font", hal yang biasanya ada dittf
,otf
atau format file apa pun Anda. menggunakan.Mesin terbang adalah representasi dari simbol tertentu, dan karena mereka adalah representasi yang bergantung pada himpunan tertentu, Anda tidak bisa hanya berharap untuk memiliki 2 simbol serupa atau bahkan identik "lebih baik", itu adalah frase yang tidak masuk akal jika Anda mempertimbangkan konteksnya, Anda setidaknya harus menentukan font atau kumpulan mesin terbang apa yang Anda pertimbangkan ketika Anda merumuskan pertanyaan seperti ini.
Apa yang biasanya digunakan untuk memecahkan masalah yang mirip dengan yang Anda hadapi, ini adalah OCR, pada dasarnya perangkat lunak yang mengenali dan membandingkan mesin terbang, Jika C # menyediakan OCR secara default, saya tidak tahu itu, tetapi umumnya sangat buruk ide jika Anda tidak benar-benar membutuhkan OCR dan Anda tahu apa yang harus dilakukan dengannya.
Anda mungkin dapat menafsirkan buku fisika sebagai buku Yunani kuno tanpa menyebutkan fakta bahwa OCR umumnya mahal dalam hal sumber daya.
Ada alasan mengapa karakter-karakter itu dilokalkan dengan cara dilokalkan, jangan lakukan itu.
sumber
Anda dapat menggambar kedua karakter dengan gaya dan ukuran font yang sama dengan
DrawString
metode. Setelah dua bitmap dengan simbol dibuat, dimungkinkan untuk membandingkannya piksel demi piksel.Keuntungan dari metode ini adalah Anda tidak hanya dapat membandingkan karakter yang sama secara absolut, tetapi juga serupa (dengan toleransi yang pasti).
sumber