Sözlük vs Liste


30

Bu yüzden Dictionary<int, int>bugün işteydim. Bu bana biraz garip geldi çünkü List<int>bunun yerine muhtemelen kullanırdım. Bir fark var mı ve bir yapının diğerine tercih edileceği bir kullanım durumu var mıydı?


1
Verilen iki (veya daha fazla) arasında belirtilen bir ilişki olması gerekiyor mu? Sonra harita (bu dilde sözlük) anlamlıdır.
Teçhizat

3
Sözlük ismi bana açıklık kazandırıyor. Hızlı bir şey aramak gerektiğinde, bir sözlük kullanın.
ChaosPandion

2
@ChaosPandion: bir List<T>.NET çerçevesi, bir arama işlemi, tipik olarak bir rastgele erişim dizidir içinde daha hızlı bir göre daha Dictionary<int,T>.
Doktor Brown,

2
@DocBrown - Yalnızca sayısal dizini anahtar olarak kullanmak oldukça tuhaf bir durumda. Diğer akıllıca bir aramak, kullanırken daha hızlı olacaktır Dictionary<TKey, TValue>.
ChaosPandion

2
@chaos bu soru hakkında bu garip durumda.
MarkJ

Yanıtlar:


32

Eğer Dictionary<int, int>indekslerinizin sadece pozisyon yerleştirmenin yanı sıra özel bir anlamı varsa, bir a kullanırsınız .

Akla gelen en yakın örnek, bir veritabanında bir id sütunu ve bir int sütunu depolamaktır. Örneğin, bir [person-id]sütununuz ve bir [personal-pin]sütununuz varsa, bunları bir içine getirebilirsiniz Dictionary<int, int>. Bu yol pinDict[person-id]size bir PIN verir, ancak dizin anlamlıdır ve yalnızca a'daki bir konum değildir List<int>.

Fakat gerçekte, iki ilişkili tamsayı listeniz olduğunda, bu uygun bir veri yapısı olabilir.


Kişisel kimliğim 0, ..., 999 aralığındaysa ve kişisel pin değerlerini 1000 kişinin tümü için belleğe yüklemek zorunda kalırsam, tipik olarak List<int>bir sözlük seçer , bir sözlük seçerdim . Aşağıdaki cevaba bakınız.
Doktor Brown,

3
evet ama bir sözlük seyrek olabilir
jk.

@jk: bu tam olarak cevabımda detaylandırmaya çalıştığım şeydi.
Doktor Brown,

7
Kişisel Şifre? Biraz gereksiz geliyor.
Jack,

Hm, endeksin "özel bir anlamı" olduğunda, gerçek dünya senaryolarında, bitişik bir aralık oluşturmamış olmaları muhtemel olabilir [0, ..., n] (bu zorunlu olmasa da) yanlış değil, kesin değil. Bununla birlikte, IMHO kararının bu "özel anlamlı şey" e dayanmaması gerekir, ancak sadece "anahtarlar yaklaşık bir aralık oluşturur [0, ..., n]". Olumlu oy sayısına göre çoğu okuyucunun bu noktayı kaçırdığını düşünüyorum.
Doc Brown

28

ListBir dizi ve Dictionarybir karma tablo olarak düşünün . Yalnızca Dictionarydeğerlerin anlamlı anahtarlarını eşlemek (veya ilişkilendirmek) gerektiğinde, Listyalnızca değerlerin konumlarını (veya dizinlerini) eşleştiren (veya ilişkilendiren) kullanırsınız.

Örneğin, bir kişinin yaşı ile boyu arasında bir ilişki kurmak istediğinizi varsayalım. Bir Dictionary<int, int>kişinin yaşını (an int) boyuna (an int) eşlemek için bir kullanabilirsiniz :

Dictionary<int, int> personHeightMap = new Dictionary<int, int>();

personHeightMap.Add(21, 185);
personHeightMap.Add(31, 174);

int height = personHeightMap.ContainsKey(21) ? personHeightMap[21] : -1;

Çok kullanışlı bir örnek değil, ama mesele şu ki, bunu zarif bir şekilde yapamazsınız Listçünkü bu değerleri pozisyonel olarak saklaması gerekir.


7
+1 söz için Listolan fiyatları için , burada bir Dictionaryile fiyatları birlikte . Verilerinizi her seferinde belirli bir sıraya göre almanız gerekiyorsa veya bunların birbirleriyle ilişkili sıraları önemlidir, a List. Dictionariessırasız olma eğilimindedir ve anahtar -> değer ilişkilerini eşleme ile ilgilenir.
KChaloux

2
Sonuncusu, ne aradığınızı bildiğiniz zaman, hash tablosu O (1) civarındadır, dizi ise en iyi durumda O (logN) iken (s / o kopyalar) ve O (N) 'de En kötü durum.
JensG

1
+1. Başka hiç kimse, listelerin anlamsal olarak sıralandığı ve sonuçların kesinlikle temel olan anlamsal aramalar olduğuna değinmiyor gibi görünüyor .
Benjamin Hodgson

15

Anlamsal olarak, a Dictionary<int, T>ve List<T>çok benzerler, her ikisi de .NET çerçevesinin rastgele erişim kapsayıcılarıdır. Bir listeyi sözlük yerine koymak için , listenizdeki boş alanları temsil etmek için türünüzde T(benzeri null) özel bir değere ihtiyacınız vardır . TGibi bir null tür değilse , yerine intkullanabilirsiniz int?veya yalnızca pozitif değerleri saklamak için bekliyorsanız, boş yuvaları temsil etmek için -1 gibi özel bir değer de kullanabilirsiniz.

Hangisini seçeceğiniz, anahtar değerlerinin aralığına bağlı olmalıdır. Dictionary<int, T>İçindeki anahtarlarınız bir tamsayı aralığındaysa, aralarında çok fazla boşluk bırakılmadan (örneğin, [0, ... 100] 'den 80 değer), o zaman a List<T>daha uygun olacaktır, çünkü indekse göre erişim daha hızlı olur ve Bu durumda sözlüğe kıyasla daha az bellek ve zaman yükü vardır.

Anahtar değerleriniz int[0, ..., 1000000] gibi bir aralıktan 100 List<T>değerse, sözlüğünüzün T değerinde 100 değerinde bir büyüklük sırasına göre sadece belleğe ihtiyaç duyacağı bir T'nin 1000000 değerinde T değerine sahip olması gerekir. 100 int değeri (artı bazı ek yükler, gerçekte bu 100 anahtarı ve değeri saklamak için hafızanın 2 katı kadar bekler). Böylece ikinci durumda bir sözlük daha uygun olacaktır.


6
bu önemli fark imho, Sözlük <int, int> seyrek olabilir
jk.

Bu durumda, <KeyValuePair <int, int >> Listini kullanamaz mıyız? Hangisi doğrusal geçiş için daha iyi olurdu?
Deepak Mishra

@DeepakMishra: Buradaki temel fark, List<KeyValuePair<int,T>>O (1) arama işlemi yok. İkincisi, içindeki öğelerin List<KeyValuePair<int,T>>kilit değerlerinden bağımsız olarak belirli bir sıralaması olabilir. İkincisine ihtiyacın olursa, eskisine değil List<KeyValuePair<int,T>>veya List<Tuple<int,T>>daha iyi bir seçenek olabilir. İkisine de ihtiyacınız varsa, o da var OrderedDictionary.
Doktor Brown,

@DocBrown Doğrusal geçiş (hangisi foreach) ve uç operasyonu için hangisi daha iyi olurdu, doğrudan bakmaya gerek yok mu?
Deepak Mishra

@DeepakMishra: Yazılım geliştirmede "genellikle daha iyi" diye bir şey yoktur. Burada daha iyisi daha hızlı, daha iyi okumak, daha az kod yazması, gelecek gereksinimler için daha kolay genişletilmesi anlamına gelebilir. Ancak genel olarak, bunu düşünmeyi bırakın, sorununuzu elinizde doğru çözen ve gözlerinizde en basit olanı uygulayın , amacınız için yeterince hızlı olup olmadığını kontrol edin ve dezavantajları gözlemlediğinizde yalnızca daha fazla düşünce yatırın.
Doktor Brown,

6

Birileri onları nasıl eşdeğer olarak görebilir?

Sözlük seyrektir ve rastgele yerleştirmelere izin verir, ancak sıralı geçişi bir sorun haline getirir, Liste seyrek değildir ve sıra dışı yerleştirme pahalıdır, doğal olarak sıralı geçişi sağlar.

Birinin diğerinden çarpıcı biçimde üstün olmadığı çok az durum olabilirdi.


2

Bir kenara: Diğer programlama dilleri, bu tür veri yapısını bir Sözlük yerine Harita olarak adlandırır.

Verileriniz anahtar / değer çiftleri olarak anlamlı bir şekilde tanımlanabiliyorsa, anahtarını kullanarak bir değer bulmanız gerekiyorsa Sözlük daha hızlı erişim sağlar.

Örneğin, bir Müşteriler listeniz olduğunu varsayalım. Her Müşteri bir ad ve adres gibi ayrıntılar ve benzersiz bir müşteri numarası içerir. Ayrıca işlenmekte olan bir Siparişler listeniz olduğunu varsayalım. Her Sipariş ne yapıldığına ilişkin detayları içerecek ve sipariş eden kişinin müşteri numarasını da içermelidir.

Bir sipariş gönderilmeye hazır olduğunda, gönderilecek adresi bulmanız gerekir. Müşteriler düz bir Liste olarak saklanırsa, müşteriyi doğru müşteri numarasına sahip bulmak için tüm listeyi aramanız gerekir. Bunun yerine, müşterileri bir sözlükte, müşteri numarası olarak anahtar olarak saklayabilirsiniz. Sözlük şimdi, herhangi bir arama yapmadan doğru müşteriyi bir adımda çıkarmanıza izin verecektir.


1

Sözlük veri aramak için karma kullanır. Sözlük, önce anahtar için bir karma değeri hesapladı ve bu karma değeri, hedef veri kovasına götürür. Bundan sonra, kovadaki her elemanın eşitlik için kontrol edilmesi gerekir. Fakat aslında liste, ilk adımdaki aramadan daha hızlı olacaktır çünkü ilk adımda aranacak hiçbir şey yoktur. Ancak ikinci adımda, listenin ilk maddeye, sonra ikinci maddeye bakması gerekir. Bu yüzden her adımda arama daha fazla zaman alıyor. Liste büyüdükçe daha uzun sürer.

Hakkında daha fazla .... Örnek ile Sözlük Vs Listesi .


-1

Söz konusu kod, iki ilişkili değer kümesini saklıyorsa, Sözlük sınıfı, bir anahtarı kullanarak değerleri aramak için dizine alınmış bir yol sağlar. Yalnızca bir değer kümesi varsa, ancak bu kümeye rastgele erişilmesi gerekiyorsa (belki bir kümedeki bir anahtarın varlığını denetlemek için) ve değerler benzersizse, HashSet kullanılacak en iyi küme sınıf olabilir.


-3

Bunlar, üsleri örtüyor gibi görünen harika cevaplar.

Sunacağım bir diğer husus, Sözlüklerin (C #) kodlama açısından daha karmaşık olduğu yönünde. Aynı kod tabanında hem listelerin hem de sözlüklerin bulunması, her iki yöntemin de nesne verilerini arama ve marşalize etme gibi temel işlemlerin nasıl yapıldığına dair ince farklara sahip olmasını sağlamak için kodunuzu zorlaştırır. Benim bakış açım, haklı bir sebepten dolayı bir sözlüğe ihtiyacınız olmadığı sürece bir liste kullanın.


8
Katılmıyorum. Sözlük / harita, her yazılım mühendisinin yakından tanıması gereken temel bir veri yapısıdır. Her iki şekilde de: herhangi bir veri yapısını kullanmak için haklı bir nedene ihtiyacınız olacaktır; List dahil
Steven Evers
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.