C# 如何打开列表<;ExpandoObject>;分组<;关键、价值>;独特的价值观?

C# 如何打开列表<;ExpandoObject>;分组<;关键、价值>;独特的价值观?,c#,linq,C#,Linq,我正在使用CsvHelper解析CSV文件。我使用的是helper.GetRecords().ToList()返回一个列表 列表中的每个ExpandoObject表示CSV文件中的一行,ExpandoObject的每个属性对应于CSV文件的一列,该列中的属性根据列标题命名 编辑我收到许多不同的CSV文件,每个文件都有不同的标题和值。这里的想法是让控制器返回CSV文件中的标题列表以及在每列中找到的所有唯一值 示例(CSV数据) 我想要这样的(List) var results = helper.G

我正在使用
CsvHelper
解析CSV文件。我使用的是
helper.GetRecords().ToList()
返回一个
列表

列表中的每个
ExpandoObject
表示CSV文件中的一行,
ExpandoObject
的每个属性对应于CSV文件的一列,该列中的属性根据列标题命名

编辑我收到许多不同的CSV文件,每个文件都有不同的标题和值。这里的想法是让控制器返回CSV文件中的标题列表以及在每列中找到的所有唯一值

示例(CSV数据)

我想要这样的(
List

var results = helper.GetRecords<dynamic>();
var item = (IDictionary<string,object>) results.First();
foreach(var prop in (IDictionary<string,object>)item){
   console.WriteLine($"{prop.Key} : {prop.Value}");
}
//ID : 1
//Name: Mickey
//State: FL
//Age: 50
注意解决方案不一定是一个组——它可以是一个
i词典

高级解决方案: 使用投影(选择)创建所需的4个新对象(可以是匿名对象或预定义对象)。 然后,可以对相同的对象使用union操作符来删除重复项。(如果您使用匿名类型,则无需传递自定义相等比较器)

高级解决方案: 使用投影(选择)创建所需的4个新对象(可以是匿名对象或预定义对象)。
然后,可以对相同的对象使用union操作符来删除重复项。(如果您是匿名类型,则无需传递自定义相等比较程序)

由于您有一组定义良好的标题,因此可以创建一个类来表示您的记录,并按如下方式读取:

var results = helper.GetRecords<Person>();
public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string State { get; set; }
    public int Age { get; set; }
}
然后在阅读时,您可以遍历每个属性并创建一个唯一值列表

var list = new Dictionary<string, dynamic>();
foreach (var prop in typeof(Person).GetProperties())
{
    list.Add(prop.Name, results.Select(x => prop.GetValue(x)).Distinct());
}
var list=newdictionary();
foreach(typeof(Person.GetProperties()中的var prop)
{
list.Add(prop.Name,results.Select(x=>prop.GetValue(x)).Distinct());
}

由于您有一组定义良好的标题,因此可以创建一个类来表示您的记录,并按如下方式读取:

var results = helper.GetRecords<Person>();
public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string State { get; set; }
    public int Age { get; set; }
}
然后在阅读时,您可以遍历每个属性并创建一个唯一值列表

var list = new Dictionary<string, dynamic>();
foreach (var prop in typeof(Person).GetProperties())
{
    list.Add(prop.Name, results.Select(x => prop.GetValue(x)).Distinct());
}
var list=newdictionary();
foreach(typeof(Person.GetProperties()中的var prop)
{
list.Add(prop.Name,results.Select(x=>prop.GetValue(x)).Distinct());
}

您需要的是在按每个键/属性及其关联值进行分组之前将列表展平。这将产生您想要的结果

    var group = results
                .SelectMany(r => r)
                .GroupBy(g => g.Key)
                .Select(g => new { 
                    Key = g.Key, 
                    Values = string.Join(",", g.Select(r => r.Value))
                });

    foreach(var r in group)
        Console.WriteLine("Key: " + r.Key + ", Values: " + r.Values);


HTH

您需要的是在按每个键/属性及其关联值进行分组之前将列表展平。这将产生您想要的结果

    var group = results
                .SelectMany(r => r)
                .GroupBy(g => g.Key)
                .Select(g => new { 
                    Key = g.Key, 
                    Values = string.Join(",", g.Select(r => r.Value))
                });

    foreach(var r in group)
        Console.WriteLine("Key: " + r.Key + ", Values: " + r.Values);


HTH

如果您的文件具有如您所示的定义良好的列标题,那么为什么要使用
动态
?你可以创建一个类来匹配并读取它,这样事情就简单多了?因为,这只是传递给我的控制器的许多CSV文件中的一个。每个CSV可能有不同的标题/值。我给出CSV示例只是为了更清楚地说明我想要实现的目标。为什么要进行向下投票?如果您的文件具有如您所示的定义良好的列标题,为什么要使用
dynamic
?你可以创建一个类来匹配并读取它,这样事情就简单多了?因为,这只是传递给我的控制器的许多CSV文件中的一个。每个CSV可能有不同的标题/值。我给出了CSV示例,只是为了更清楚地说明我想要实现的目标。为什么要投否决票?我缺少的是
SelectMany
!谢谢。
SelectMany
就是我丢失的那一块!谢谢