【问题标题】:Converting an IEnumerable to a lookup with multiple keys per value将 IEnumerable 转换为每个值具有多个键的查找
【发布时间】:2011-01-04 10:19:15
【问题描述】:

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"}

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

【问题讨论】:

  • 你打算如何使用这个数据结构?在这种情况下,每个值有多个键是什么意思?
  • @lpthnc:我已经编辑了问题以试图澄清。
  • 我在您接受后编辑我的答案,您可能对新版本感兴趣...

标签: c# linq data-structures dictionary lookup


【解决方案1】:

这是使用ToDictionary 的解决方案:

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

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


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

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);

它应该给出与您的代码完全相同的结果

【讨论】:

    【解决方案2】:

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

    var lookup = (from word in words
                  from c in word
                  select new { Word = word, Character = c }).ToLookup(x => x.Character, x => x.Word);
    

    【讨论】:

      【解决方案3】:

      您是否考虑过改用Trie

      C# implementation of a Trie

      【讨论】:

        【解决方案4】:
        // { 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);
        

        【讨论】:

          猜你喜欢
          • 2023-03-16
          • 2013-01-23
          • 1970-01-01
          • 2019-12-14
          • 2018-06-24
          • 2012-10-30
          • 2013-10-20
          • 2022-11-26
          • 1970-01-01
          相关资源
          最近更新 更多