2010-01-12 39 views
2

IEnumerable轉換爲查看字典式結構但每個值具有多個鍵的最佳方式是什麼?
我正在尋找的東西,大致做同樣的事情,因爲這,並且在一般的方式:將IEnumerable轉換爲每個值具有多個鍵的查找

var wordsByLetter = new Dictionary<char, HashSet<string>>(); 
foreach (string word in words) 
{ 
    foreach (char letter in word.Distinct()) 
    { 
     if (!wordsByLetter.ContainsKey(letter)) 
     { 
      wordsByLetter.Add(letter, new HashSet<string>()); 
     } 
     wordsByLetter[letter].Add(word); 
    } 
} 

所以結果是一個字典映射使用含有該組詞中的每個字母信。
例如,如果words包含{"foo", "faz", "zoo"}然後將得到的字典將包含:

'a' -> {"faz"} 
'f' -> {"foo", "faz"} 
'o' -> {"foo", "zoo"} 
'z' -> {"faz", "zoo"} 

我可以把我的代碼示例爲一個擴展方法,但有一個內置的功能或更好的算法使用?

+0

你怎麼打算用這個數據結構?在這種情況下,每個值的多個鍵是什麼意思? – 2010-01-12 23:46:55

+0

@lpthnc:我編輯了這個問題,試圖澄清。 – Whatsit 2010-01-12 23:55:45

+0

我接受後編輯我的答案,您可能會對新版本感興趣... – 2010-01-13 00:11:19

回答

5

下面是一個使用的解決方案ToDictionary

var wordsByLetter = 
    words.SelectMany(word => word.ToCharArray()) 
     .Distinct() 
     .ToDictionary(
      letter => letter, 
      letter => words.Where(word => word.Contains(letter))); 

注意,它肯定比你的代碼效率較低,自言集合枚舉一次得到不同的字母,然後一次爲每個信...


更新:其實我有一個MUC H以下有效建議:

var wordsByLetter = 
    (from word in words 
    from letter in word 
    group word by letter into grp 
    select new 
    { 
     Letter = grp.Key, 
     Words = new HashSet<string>(grp) 
    }) 
    .ToDictionary(x => x.Letter, x => x.Words); 

它應該給完全相同的結果作爲你的代碼

+0

+1我什麼時候可以在Linq上購買您的書,謝謝, – BillW 2010-01-13 02:17:59

5

ToLookup是您需要的擴展方法。例如:

var lookup = (from word in words 
       from c in word 
       select new { Word = word, Character = c }).ToLookup(x => x.Character, x => x.Word); 
0
// { foo, faz } -> { f|foo, o|foo, f|faz, a|faz, z|faz } 
var pairs = words.SelectMany(w => 
    w.Distinct().Select(l => new { Word = w, Letter = l })); 

var map = pairs.ToLookup(p => p.Letter, p => p.Word); 
相關問題