将带有List的字典转换为IEnumerable

时间:2015-02-11 10:20:44

标签: c# dictionary ienumerable

我有一本字典:

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

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

Dictionary<String, IEnumerable<Foo>>

有没有简单的方法可以做到这一点,而不是通过我的原始字典进行显而易见的循环并手动完成?

3 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:2)

使用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>
}

答案 2 :(得分:0)

我也试过这条路线,将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>() { ... };
    
  • “多个值”已定义为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值的另一个词典就像尝试将方形钉插入圆孔中一样。更合适,更安全的方法(从面向对象的角度来看)是将读/写字典转换为查找。这为您提供了只读对象的真正安全性(Foo项除外,它们可能不是永久的)。

我甚至会说大多数时候使用ReadOnlyDictionary时,您可以使用ILookup并获得相同的功能。