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


6
Apa yang salah dengan menggunakan StringComparer.InvariantCultureIgnoreCase? Ia melakukan apa yang dikatakannya ...
leppie

5
Saya belum pernah mendengarnya, karena itu pertanyaannya!
Tn. Boy


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.


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"]);

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")))


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!");

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){}
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.