如何将List <ExpandoObject>转换为唯一值的Group <key,value>?

时间:2019-08-26 20:25:08

标签: c# linq

我正在使用CsvHelper解析CSV文件。我正在使用helper.GetRecords<dynamic>().ToList();返回一个List<ExpandoObject>

列表中的每个ExpandoObject代表CSV文件中的一行,而ExpandoObject的每个属性对应于CSV文件的一列,其中该属性是根据列标题来命名的。

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

示例(CSV数据)

ID, Name, State, Age
1,Mickey,FL,50
2,Minnie,FL,48
3,Donald,AK,48

我会有这样的东西(List<IDictionary<string,object>>

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

我要做什么

由于IDictionary<string,object>中的每个List都包含同一组Keys,因此我想像这样使用Group<key,List<uniquevalues>>

Group Key: "ID"
   Values: ["1","2","3"]

Group Key: "Name"
   Values: ["Mickey","Minnie","Donald"]

Group Key: "State"
   Values: ["FL","AK"]

Group Key: "Age"
   Values: ["50","48"]

注意,解决方案不一定非要是Group,它可以是IDictionary<key, List<unique value>>

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

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

var results = helper.GetRecords<Person>();

在这里,Person是代表您的CSV列的类,如下所示:

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

答案 2 :(得分:0)

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

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

See working fiddle here

HTH