2010-01-12 44 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); 
相关问题