将带有 List 的字典转换为 IEnumerable

Convert dictionary with List to IEnumerable

我有字典:

Dictionary<String, List<Foo>> test = new Dictionary<String, List<Foo>>();

然后我填充这个字典,因此我需要这个列表以便我可以调用 Add()。我的问题是函数需要 return:

Dictionary<String, IEnumerable<Foo>>

有没有简单的方法可以做到这一点,而不用做显而易见的事情并循环遍历我原来的字典并手动完成?

return dictionary.ToDictionary(x => x.Key,x => x.Value.AsEnumerable())

使用 List<Foo> 添加内容比使用 Dictionary<String, IEnumerable<Foo>> 更高效、更容易。这没问题,因为 List<Foo> 实现了 IEnumerable<Foo>,甚至不需要转换。

所以像这样(伪代码):

var test = new Dictionary<String, IEnumerable<Foo>>();
foreach(var x in something)
{
    var list = new List<Foo>();
    foreach(var y in x.SomeCollection)
        list.Add(y.SomeProperty);
    test.Add(x.KeyProperty, list); // works since List<T> is also an IEnumerable<T>
}

我也尝试了这条路线,将 Dictionary<string, List<Foo>> 转换为 ReadOnlyDictionary<string, IEnumerable<Foo>>。当我试图转换为只读字典时,将 List 转换为 IEnumerable 的全部目的是创建一个只读集合。 OP 方法的问题是:

Dictionary<string, List<string>> errors = new Dictionary<string, List<string>>();

errors["foo"] = new List<string>() { "You can't do this" };

Dictionary<string, IEnumerable<string>> readOnlyErrors = // convert errors...

readOnlyErrors["foo"] = new List<string>() { "I'm not actually read-only!" };

IEnumerable<Foo> 的出现让您认为这是只读且安全的,但实际上并非如此。看完问题 LINQ Convert Dictionary to Lookup 后,Lookup 对象更合适,因为它允许您:

  • 将一个键与多个值相关联

  • 您不能用新值覆盖键

    // This results in a compiler error
    lookUp["foo"] = new List<Foo>() { ... };
    
  • "multiple values"已经定义为IEnumerable<T>

  • 您仍然可以使用相同的外循环和内循环算法来提取单个值:

    ILookup<string, string> lookup = // Convert to lookup
    
    foreach (IGrouping<string, string> grouping in lookup)
    {
        Console.WriteLine(grouping.Key + ":");
    
        foreach (string item in grouping)
        {
            Console.WriteLine("    item: " + item);
        }
    }
    

Dictionary<string, List<Foo>> 转换为 ILookup<string, Foo>

这是一个快速的双线:

Dictionary<string, List<Foo>> foos = // Create and populate 'foos'

ILookup<string, Foo> lookup = foos.SelectMany(item => item.Value, Tuple.Create)
                                  .ToLookup(p => p.Item1.Key, p => p.Item2);

现在您可以使用与 Dictionary<string, IEnumerable<Foo>>:

相同的两步循环
foreach (IGrouping<string, Foo> grouping in lookup)
{
    string key = grouping.Key;

    foreach (Foo foo in grouping)
    {
        // Do stuff with key and foo
    }
}

来源:LINQ Convert Dictionary to Lookup

转换为另一个具有 IEnumerable 值的字典就像试图将方钉塞入圆孔。更合适、更安全的方法(从面向对象的角度来看)是将 read/write 字典转换为查找。这为您提供了只读对象的真正预期安全性(Foo 项除外,它们可能不是不可变的)。

我什至可以说,大多数情况下,当使用 ReadOnlyDictionary 时,您可以使用 ILookup 并获得相同的功能。