Saya memiliki aplikasi yang menggunakan dll yang dikelola. Salah satu dari itu dll mengembalikan kamus generik:
Dictionary<string, int> MyDictionary;
Kamus berisi tombol dengan huruf besar dan kecil.
Di sisi lain saya mendapatkan daftar kunci potensial (string) namun saya tidak dapat menjamin kasus ini. Saya mencoba mendapatkan nilai dalam kamus menggunakan tombol. Tetapi tentu saja hal berikut ini akan gagal karena saya memiliki kasus ketidakcocokan:
bool Success = MyDictionary.TryGetValue( MyIndex, out TheValue );
Saya berharap TryGetValue akan memiliki flag kasus abaikan seperti yang disebutkan dalam dokumen MSDN , tetapi tampaknya ini tidak valid untuk kamus umum.
Apakah ada cara untuk mendapatkan nilai dari kamus itu dengan mengabaikan case utama? Apakah ada solusi yang lebih baik daripada membuat salinan kamus baru dengan parameter StringComparer.OrdinalIgnoreCase yang tepat ?
sumber
Jawaban:
Tidak ada cara untuk menentukan
StringComparer
pada titik di mana Anda mencoba untuk mendapatkan nilai. Jika Anda memikirkannya,"foo".GetHashCode()
dan"FOO".GetHashCode()
sama sekali berbeda sehingga tidak ada cara yang masuk akal Anda bisa menerapkan get-case sensitif pada peta hash yang case-sensitive.Anda dapat, bagaimanapun, membuat kamus case-sensitive di tempat pertama menggunakan: -
Atau buat kamus case-sensitive baru dengan isi dari kamus case-sensitive yang ada (jika Anda yakin tidak ada tabrakan kasus): -
Kamus baru ini kemudian menggunakan
GetHashCode()
implementasinyaStringComparer.OrdinalIgnoreCase
jadicomparer.GetHashCode("foo")
dancomparer.GetHashcode("FOO")
memberi Anda nilai yang sama.Sebagai alternatif, jika hanya ada beberapa elemen dalam kamus, dan / atau Anda hanya perlu mencari sekali atau dua kali, Anda dapat memperlakukan kamus asli sebagai
IEnumerable<KeyValuePair<TKey, TValue>>
dan hanya mengulanginya: -Atau jika Anda suka, tanpa LINQ: -
Ini menghemat biaya pembuatan struktur data baru, tetapi sebagai imbalannya biaya pencarian adalah O (n) bukan O (1).
sumber
default(KeyValuePair<T, U>)
bukannull
- itu adalah diKeyValuePair
manaKey=default(T)
danValue=default(U)
. Jadi Anda tidak dapat menggunakan?.
operator dalam contoh LINQ; Anda harus mengambilFirstOrDefault()
dan kemudian (untuk kasus khusus ini) periksa untuk melihat apakahKey == null
.Bagi Anda para LINQer di luar sana yang tidak pernah menggunakan konstruktor kamus reguler:
sumber
Ini tidak terlalu elegan tetapi jika Anda tidak dapat mengubah pembuatan kamus, dan yang Anda butuhkan adalah hack kotor, bagaimana dengan ini:
sumber
ToUpperInvariant
sebagai gantinyaToLower
. msdn.microsoft.com/en-us/library/dd465121%28v=vs.110%29.aspxvar item = MyDictionary.FirstOrDefault(x => x.Key.ToUpperInvariant() == keyValueToCheck.ToUpperInvariant());
dict.Keys.Contains("bla", appropriate comparer)
? Selain itu, Anda tidak akan mendapatkan null untuk FirstOrDefault karena keyvaluepair di C # adalah sebuah struct.