将IEnumerable转换为每个值具有多个键的查找

Wha*_*sit 2 c# linq lookup dictionary data-structures

将数据转换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);
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,结果是一个字典映射用于包含该字母的单词集的每个字母.
例如,如果words包含,{"foo", "faz", "zoo"}则生成的字典将包含:

'a' -> {"faz"}
'f' -> {"foo", "faz"}
'o' -> {"foo", "zoo"}
'z' -> {"faz", "zoo"}
Run Code Online (Sandbox Code Playgroud)

我可以将我的代码示例转换为扩展方法,但是是否有内置函数或更好的算法可供使用?

eul*_*rfx 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);
Run Code Online (Sandbox Code Playgroud)


Tho*_*que 5

这是一个解决方案ToDictionary:

var wordsByLetter =
    words.SelectMany(word => word.ToCharArray())
         .Distinct()
         .ToDictionary(
            letter => letter,
            letter => words.Where(word => word.Contains(letter)));
Run Code Online (Sandbox Code Playgroud)

请注意,它肯定比你的代码效率低,因为单词集合被枚举一次以获得不同的字母,然后每个字母一次......


更新:实际上我有一个更有效的建议:

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);
Run Code Online (Sandbox Code Playgroud)

它应该提供与您的代码完全相同的结果