Kamus Case-INsensitive dengan tipe kunci string dalam C #

156

Jika saya punya Dictionary<String,...>, mungkinkah membuat metode seperti ContainsKeycase-insensitive?

Ini sepertinya terkait, tetapi saya tidak memahaminya dengan benar: c # Kamus: membuat Key case-insensitive melalui deklarasi

Pak Boy
sumber
6
Apa yang salah dengan menggunakan StringComparer.InvariantCultureIgnoreCase? Ia melakukan apa yang dikatakannya ...
leppie
5
Saya belum pernah mendengarnya, karena itu pertanyaannya!
Tn. Boy
2
Kemungkinan duplikat dari akses yang tidak peka terhadap Case untuk kamus umum
Michael Freidgeim
Pertanyaan itu terkait, tetapi bukan duplikat dari pertanyaan ini. Yang itu masuk ke bagaimana menangani kamus yang ada. Saya mulai dengan kode baru, jadi jawaban di sini lebih cocok.
selamat tinggal

Jawaban:

322

Ini sepertinya terkait, tetapi saya tidak memahaminya dengan benar: c # Kamus: membuat Key case-insensitive melalui deklarasi

Ini memang terkait. Solusinya adalah dengan memberi tahu contoh kamus untuk tidak menggunakan metode perbandingan string standar (yang sensitif huruf besar) melainkan menggunakan huruf besar yang tidak sensitif. Ini dilakukan dengan menggunakan konstruktor yang sesuai :

var dict = new Dictionary<string, YourClass>(
        StringComparer.InvariantCultureIgnoreCase);

Konstruktor mengharapkan IEqualityCompareryang memberi tahu kamus cara membandingkan kunci.

StringComparer.InvariantCultureIgnoreCasememberi Anda IEqualityComparercontoh yang membandingkan string dengan cara case-insensitive.

Konrad Rudolph
sumber
1
Sempurna, saya entah bagaimana melewatkan cara seperti STL untuk melewatkan pembanding ke dalam ctor.
Tn. Boy
7
Tidak pernah berhenti membuat saya takjub bagaimana saya selalu menemukan jawaban untuk pertanyaan pengkodean di sini! Mungkin saya akan memberi nama kucing saya berikutnya setelah Anda, Konrad! :-)
Jamie
10
Kemungkinan, komparator StringComparison.OrdinalIgnoreCase lebih cepat daripada berbasis kultur: stackoverflow.com/questions/492799/…
Manushin Igor
Bagaimana saya melakukannya jika saya tidak membuat kamus tetapi mencoba menggunakan ContainsKey () untuk kecocokan kunci case-case pada kamus yang ada yang saya dapatkan sebagai bagian dari suatu objek?
Shridhar R Kulkarni
1
@ShridharRKulkarni Anda pada dasarnya tidak bisa (efisien). Logika perbandingan adalah bagian inti dari struktur data kamus internal. Untuk memungkinkan ini, wadah harus mempertahankan beberapa indeks untuk datanya, dan kamus tidak melakukan ini.
Konrad Rudolph
21
var myDic = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
myDic.Add("HeLlo", "hi");

if (myDic.ContainsKey("hello"))
    Console.WriteLine(myDic["hello"]);
Steve
sumber
1
Cuplikan kode mengatakan itu semua. Sangat membantu. Tidak yakin mengapa postingan ini memiliki upvotes yang lebih sedikit dibandingkan dengan jawaban yang diterima hanya karena terlambat 3 menit.
RBT
14

Ada beberapa kemungkinan di mana Anda berurusan dengan kamus yang ditarik dari pihak ke-3 atau dll eksternal. Menggunakan LINQ

YourDictionary.Any(i => i.KeyName.ToLower().Contains("yourstring")))

Kurkula
sumber
3
Ini sangat bagus. Namun, kata hati-hati, jika Anda berubah Anyke SingleOrDefaultAnda tidak akan nullkembali jika itu tidak ada, sebaliknya Anda akan mendapatkan nilai kuncipasangan dengan kedua kunci dan nilai diatur ke null!
NibblyPig
1
ContainsSepertinya kasus penggunaan yang sangat spesifik untuk sesuatu yang sedang Anda kerjakan saat itu. Sebagai jawaban yang lebih umum dan bermanfaat, saya pikir Equalslebih baik. Dan pada catatan yang sama, alih-alih menduplikasi string ToLower(), Akan lebih baik untuk digunakan StringComparison.xxxCase.
Suamere
1
ini sangat berguna dan menyingkirkan ToLower jelas merupakan peningkatan - kasus penggunaan saya adalah: return AppliedBuffs.Any (b => b.Key.Equals (Nama, StringComparison.OrdinalIgnoreCase)); case-insensitive sempurna Berisi pada kamus case-sensitive.
David Burford
Saya sangat tergoda untuk memilih ini. Kata hati-hati, jika Anda adalah pemilik kamus ini tentu bukan cara untuk melakukannya. Hanya gunakan pendekatan ini jika Anda tidak tahu bagaimana kamus itu dipakai. Bahkan kemudian, untuk kecocokan string yang tepat (bukan hanya kecocokan sebagian), gunakan dict.Keys.Contains("bla", appropriate comparer)kelebihan LINQ untuk kemudahan penggunaan.
nawfal
1

Saya baru saja mengalami masalah yang sama di mana saya membutuhkan kamus caseInsensitive dalam pengontrol ASP.NET Core.

Saya menulis metode ekstensi yang melakukan trik. Mungkin ini bisa bermanfaat bagi orang lain juga ...

public static IDictionary<string, TValue> ConvertToCaseInSensitive<TValue>(this IDictionary<string, TValue> dictionary)
{
    var resultDictionary = new Dictionary<string, TValue>(StringComparer.InvariantCultureIgnoreCase);
    foreach (var (key, value) in dictionary)
    {
        resultDictionary.Add(key, value);
    }

    dictionary = resultDictionary;
    return dictionary;
}

Untuk menggunakan metode ekstensi:

myDictionary.ConvertToCaseInSensitive();

Kemudian dapatkan nilai dari kamus dengan:

myDictionary.ContainsKey("TheKeyWhichIsNotCaseSensitiveAnymore!");
Ferry Jongmans
sumber
0

Jika Anda tidak memiliki kendali dalam pembuatan instance, misalkan objek Anda didesterilasi dari json dll, Anda dapat membuat kelas wrapper yang diwarisi dari kelas kamus.

public class CaseInSensitiveDictionary<TValue> : Dictionary<string, TValue>
{
    public CaseInSensitiveDictionary() : base(StringComparer.OrdinalIgnoreCase){}
}
AG
sumber