Anahtar yoksa C # Dictionary <int, int> aramasına ne olur?


121

Boş değeri kontrol etmeyi denedim, ancak derleyici bu koşulun asla oluşmayacağı konusunda uyarıyor. Ne aramalıyım?

Yanıtlar:


196

Eğer anahtar eğer değerini almak istiyorum varsayarsak yapar exist, kullanımı Dictionary<TKey, TValue>.TryGetValue:

int value;
if (dictionary.TryGetValue(key, out value))
{
    // Key was in dictionary; "value" contains corresponding value
} 
else 
{
    // Key wasn't in dictionary; "value" is now 0
}

( ContainsKeyVe sonra indeksleyici, anahtarın iki kez yukarı bakmasını sağlar, bu oldukça anlamsızdır.)

Hatta eğer Not edildi indeksleyiciyi için - null olmaz çalışmalarını kontrol referans türleri kullanarak Dictionary<,>Eksik anahtarı talep halinde yerine null adlı dönen yerine, bir özel durum oluşturur. (Bu, Dictionary<,>ve arasındaki büyük farktır Hashtable.)


@JonSkeet TryGetValue de çift arama yapmıyor mu ( bu soru metninde belirtildiği gibi )?
nawfal

5
@nawfal: Bu sorunun bunu ifade ettiğine dair bir gösterge göremiyorum. Daha fazla iş yaptığını söylüyor ContainsKey, ki bu doğru, çünkü değeri de çıkarması gerekiyor. Yine de iki arama yapmıyor.
Jon Skeet

Naif olarak, boş bekliyordum, ancak Dictionary <TKey, enum> için bu, numaralandırmada "0" eşdeğerini döndürüyor.
Jess

23

KeyNotFoundSözlük, anahtarınızın anahtarınızı içermemesi durumunda bir istisna atar .

Önerildiği gibi ContainsKey, uygun önlemdir. TryGetValueaynı zamanda etkilidir.

Bu, sözlüğün null değerini daha etkin bir şekilde saklamasına izin verir. Bu şekilde davranmadan, [] operatöründen boş bir sonucun kontrol edilmesi ya bir boş değeri ya da giriş anahtarının var olmadığını gösterir ki bu iyi değildir.



10

Yeni bir değer eklemeyi denemeden önce kontrol ediyorsanız, şu ContainsKeyyöntemi kullanın :

if (!openWith.ContainsKey("ht"))
{
    openWith.Add("ht", "hypertrm.exe");
}

Değerin var olup olmadığını kontrol ediyorsanız TryGetValue, Jon Skeet'in cevabında açıklanan yöntemi kullanın .


8
TryGet daha iyi
Ruben Bartelink

2
Çünkü, İçerir'den hemen sonra alırsanız, hashtable ile anahtar aramasını iki kez çözüyorsunuz. Wintellect PowerCollections, orada değilse ekleyecekseniz çözünürlüğü Ek'e kaydetmek için GetValueElseAddbir değer (veya a Func<TValue>) verdiğiniz yöntemlere de sahiptir . Sanırım .NET kitaplarına girememesinin nedeni, bir önbellek tarzında kullanıyorsanız Ekle yolunun daha az sıklıkta olmasıdır]
Ruben Bartelink

@rub: Sanırım bu kodun amacına bağlı. Değeri kullanmak istiyorsanız TryGetValue, bunun daha iyi olacağını kabul ediyorum , ancak yinelenen eklemelerden kaçınmak için sözlüğün anahtarı içerip içermediğini kontrol etmek istiyorsanız, ContainsKey(daha iyi değilse) aynı derecede iyi olduğunu söyleyebilirim .
Fredrik Mörk

@Fredrik: Yalnızca bir sınırlama kontrolü yapmak istiyorsanız, o zaman evet, ContainsKey kullanmaya değer. Bu cevabın örnek kodunda durumun böyle olmadığını unutmayın.
Jon Skeet

@Jon: doğru, aslında katma değerin eklendikten hemen sonra getirildiğini özledim.
Fredrik Mörk

3

Değeri çıkarmaya çalışmadan önce Dictionary.ContainsKey'i (int anahtar) kontrol etmelisiniz.

Dictionary<int, int> myDictionary = new Dictionary<int, int>();
myDictionary.Add(2,4);
myDictionary.Add(3,5);

int keyToFind = 7;
if(myDictionary.ContainsKey(keyToFind))
{
    myValueLookup = myDictionay[keyToFind];
    // do work...
}
else
{
    // the key doesn't exist.
}

2
Aramayı neden iki kez yapmasını istiyorsunuz?
Jon Skeet

2
@mookid: Bence değil. Buradaki fikir, anahtara bakmaya çalışmak ve eğer bulunursa bir eylem planı yapmak ve aksi halde başka bir eylem planı yapmaktır, değil mi?
Jon Skeet

3
@Jon - Dürüst olmak gerekirse? Çünkü bilmiyordum TryGetValue. Neyse ki şimdi yapıyorum, bu yüzden gelecekte bileceğim. Yine de bu yanıtı sağlam bırakacağım çünkü tartışma değerlidir.
ZombieSheep

@Jon Skeet - Bu yüzden buradayım. :)
ZombieSheep

@JonSkeet Çünkü C # 7'den önce TryGetValuelambda ifadesinde kullanamazsınız . Yine de bu, C # için yeni bir uzantının catch, nullbirleştirme operatörüne benzer bir operatör olacağını düşündürüyor .
NetMage

1

Yardımcı bir sınıf kullanışlıdır:

public static class DictionaryHelper
{
    public static TVal Get<TKey, TVal>(this Dictionary<TKey, TVal> dictionary, TKey key, TVal defaultVal = default(TVal))
    {
        TVal val;
        if( dictionary.TryGetValue(key, out val) )
        {
            return val;
        }
        return defaultVal;
    }
}

Bazen bunun neden standart kitaplığa eklenmediğini merak ediyorum. Hashmap kullanan hemen hemen tüm diller, giriş yoksa null döndürür, acayip bir istisna değil. Sözlüğünüzde olmayan bir öğe istisnai bir davranış değildir.
Adam Hess

@AdamHess - bu yüzden c # içinde Hashtable () var ... ne yazık ki, anahtarlarınız orada kutulu ... :(
veljkoz


0

Muhtemelen kullanmalısınız:

if(myDictionary.ContainsKey(someInt))
{
  // do something
}

Boş değeri kontrol edememenizin nedeni, buradaki anahtarın bir değer türü olmasıdır.


1
Boş değerin kontrol edilmesi istenen etkiyi yaratmayacağından, değerin türü biraz ilgisizdir.
Jon Skeet

@Johannes, Jon'un çözümü elbette çok daha iyi, ancak soruyu soran kişi anahtarın var olup olmadığını kontrol ettiğini ve bunun Sözlük <int, int> olduğunu belirtti, bu nedenle anahtar burada da bir değer türü.
Razzie

0
int result= YourDictionaryName.TryGetValue(key, out int value) ? YourDictionaryName[key] : 0;

Anahtar sözlükte mevcutsa, anahtarın değerini döndürür, aksi takdirde 0 döndürür.

Umarım bu kod size yardımcı olur.


1
Anahtar varsa, bu kod iki kez aranacaktır. TryGetValueyeterli, valueyerineresult
Mathieu VIALES

0

Bu belirli sözlüğü kapsülleme seçeneğini düşünün ve bu anahtarın değerini döndürmek için bir yöntem sağlayın:

public static class NumbersAdapter
{
    private static readonly Dictionary<string, string> Mapping = new Dictionary<string, string>
    {
        ["1"] = "One",
        ["2"] = "Two",
        ["3"] = "Three"
    };

    public static string GetValue(string key)
    {
        return Mapping.ContainsKey(key) ? Mapping[key] : key;
    }
}

Ardından bu sözlüğün davranışını yönetebilirsiniz.

Örneğin burada: eğer sözlükte anahtar yoksa, parametreye göre ilettiğiniz anahtarı döndürür.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.