使用GroupBy()时如何从select中获得与foreach相同的结果

时间:2018-11-01 18:55:04

标签: c# linq select foreach group-by

我希望能够获得与使用select方法和匿名方法时在分组上使用foreach可以获得的相同结果。

    public class ExportData
    {
        public int Id { get; set; }

        public string Colour { get; set; }

        public string Name { get; set; }

        public int Age { get; set; }

        public int Money { get; set; }
    }

    public class ExportDataDictionary
    {
        public IDictionary<string, object> ColumnData { get; set; } = new Dictionary<string, object>();
    }

以上面的两个类为例。

我创建一些数据。

        var dataCollection = new List<ExportData>
        {
            new ExportData { Name = "Name1", Age = 1, Colour = "Blue", Id = 1, Money = 10 },
            new ExportData { Name = "Name1", Age = 2, Colour = "Red", Id = 2, Money = 20 },
            new ExportData { Name = "Name1", Age = 2, Colour = "Green", Id = 3, Money = 30 },
            new ExportData { Name = "Name2", Age = 1, Colour = "Yellow", Id = 4, Money = 40 },
            new ExportData { Name = "Name3", Age = 2, Colour = "Blue", Id = 5, Money = 50 },
            new ExportData { Name = "Name4", Age = 3, Colour = "Blue", Id = 6, Money = 10 }
        };

接下来,我通过以下两个属性对数据进行分组。

 var dataGrouping = dataCollection.GroupBy(g => new { g.Name, g.Age });

然后我创建一个ExportDataDictionary的列表,并遍历分组中的每个组,每次创建一个新的ExportDataDictionary,并将两个键都添加到字典中。

        var data = new List<ExportDataDictionary>();

        foreach (var grouping in dataGrouping)
        {
            var datadictionary = new ExportDataDictionary();

            datadictionary.ColumnData.Add("NAME", grouping.Key.Name);
            datadictionary.ColumnData.Add("AGE", grouping.Key.Age);
            data.Add(datadictionary);
        }

结果是5个ExportDataDictionaries的集合,每个字典中有2列,其中包含与每个分组相对应的一对密钥。

我尝试使用Select方法实现相同效果的方法如下所示。

        var data2 = new List<ExportDataDictionary>();

        var mydata = dataGrouping.Select(d => 
        {
            var datadictionary = new ExportDataDictionary();
            datadictionary.ColumnData.Add("NAME", d.Key.Name);
            datadictionary.ColumnData.Add("AGE", d.Key.Age);
            data2.Add(datadictionary);
            return data2;
        });

结果的类型为:

mydata = {System.Linq.Enumerable.WhereSelectEnumerableIterator<System.Linq.IGrouping<<>f__AnonymousType0<string, int>, ConsoleApp2.Program.ExportData>, System.Collections.Generic.List<ConsoleApp2.Program.ExportDataDictionary>>}

,它包含5个项目,每个项目包含10个词典。我期望的5个字典的值与使用foreach时的值相同,但是每个字典有2个副本。我认为这一定是因为它正在为分组中使用的两个键创建字典。因此,我想知道如何仅对其中一个键或仅对集合中的每个组执行此操作?

要求mydata应该包含与data变量

中的foreach获得的结果相同的结果

任何帮助,不胜感激:)

1 个答案:

答案 0 :(得分:1)

只需在最后一条语句的末尾添加.ToList(),就可以删除data2.Add(datadictionary);语句,并仅返回数据字典return datadictionary;

var mydata = dataGrouping.Select(d =>
        {
            var datadictionary = new ExportDataDictionary();
            datadictionary.ColumnData.Add("NAME", d.Key.Name);
            datadictionary.ColumnData.Add("AGE", d.Key.Age);

            return datadictionary;
        }).ToList();

我已经运行了您的代码,并检查发现mydata包含5个项目,每个项目包含2个ColumnData成员。

实际上,只有在调用.ToList()函数时才执行Linq查询