2010-10-28 21 views
48

IEnumerable s aynı boyutta iki, nasıl ben Linq kullanarak birDictionarydönüştürebilirsiniz Verilen?Harita İki liste

IEnumerable<string> keys = new List<string>() { "A", "B", "C" }; 
IEnumerable<string> values = new List<string>() { "Val A", "Val B", "Val C" }; 

var dictionary = /* Linq ? */; 

Ve beklenen çıktısı:

A: Val A 
B: Val B 
C: Val C 

Ben bunu başarmak için bazı basit bir yolu olup olmadığını merak ediyorum.

Performans konusunda endişelenmeli miyim? Büyük koleksiyonum varsa ne olur? bunu yapmak için daha kolay bir yol olup olmadığını bilmiyorum


, şu anda böyle yapıyorum:

I will döngü IEnumerable bana elemanı ve dizini sağlayan bir uzantısı yöntemine sahip numara.

public static class Ext 
{ 
    public static void Each<T>(this IEnumerable els, Action<T, int> a) 
    { 
     int i = 0; 
     foreach (T e in els) 
     { 
      a(e, i++); 
     } 
    } 
} 

Ve indeksi, enumerable ve birlikte döngü bir başka Enumerable eş elemanını alır bir yöntem var.

public static Dictionary<TKey, TValue> Merge<TKey, TValue>(IEnumerable<TKey> keys, IEnumerable<TValue> values) 
{ 
    var dic = new Dictionary<TKey, TValue>(); 

    keys.Each<TKey>((x, i) => 
    { 
     dic.Add(x, values.ElementAt(i)); 
    }); 

    return dic; 
} 

O halde bunun gibi kullanın:

IEnumerable<string> keys = new List<string>() { "A", "B", "C" }; 
IEnumerable<string> values = new List<string>() { "Val A", "Val B", "Val C" }; 

var dic = Util.Merge(keys, values); 

Ve çıkış doğrudur:

.NET 4.0 (veya Rx den System.Interactive 3.5 sürümü) ile
A: Val A 
B: Val B 
C: Val C 

cevap

101

, Zip():

+0

Başparmak yukarıya .Zip. Memnuniyetle BCL'ye yapılmış. Oldukça uzun zamandır kendi versiyonum vardı. – spender

+1

@spender - Kendiniz yapmış olsanız bile, [Eric Lipperts Blog] 'dan (http://blogs.msdn.com/b/ericlippert/archive/2009/05/07/zip-me-up. aspx) – Oliver

+1

Yazık bir "Zip" yöntemine ihtiyaç var. Yalnızca daha fazla istatistik yazılan diller genel değişkenlik parametrelerini destekliyorsa, 'Seç' bunu işleyecektir (Şemadaki 'harita' gibi). – leppie

20

Veya fikrinize dayanarak, LINQ dizini sağlayan Select() bir aşırı yüklenme içerir. values endeksine göre erişimi destekler gerçeği ile birlikte, tek yapabileceği aşağıdaki:

var dic = keys.Select((k, i) => new { k, v = values[i] }) 
       .ToDictionary(x => x.k, x => x.v); 

+0

Ah, güzel! Tam olarak bunun için bakıyordum. Linq kullanışlıdır, ancak yazmanız gereken kod gerçekten kafa karıştırıcı IMO'dur. – Nyerguds

7

Ben bu yaklaşımı gibi (values, yani ... List<string> olarak tutulursa):

var dict = 
    Enumerable.Range(0, keys.Length).ToDictionary(i => keys[i], i => values[i]); 
0

Eğer MoreLINQ kullanıyorsanız, ayrıca daha önce oluşturulmuş KeyValuePair s tarihinde ToDictionary uzatma yöntemidir yararlanabilirler:

var dict = Enumerable 
    .Zip(keys, values, (key, value) => KeyValuePair.Create(key, value)) 
    .ToDictionary(); 

Ayrıca, Zip uzantısı yönteminin farklı uzunluklardaki giriş koleksiyonlarına karşı güvenli olduğu da unutulmamalıdır.