将CSV行分组为一个

时间:2012-01-24 09:15:37

标签: c# linq csv

我有一个包含行的CSV文件,其中某些列的数据仅显示在其中一行中,其他列重复其值:

Heading1, Heading2, Heading3, Heading4
1       , 2       ,         , 4
1       ,         , 3       , 4

我怎样才能最终:

Heading1, Heading2, Heading3, Heading4
1       , 2       , 3       , 4

我想对Heading1和Heading4进行分组,因为它们对于重复的行是唯一的,并获得所有其他行的第一个非空值,最后只有一个string[]

我已经在new { Header1, Header4 }上进行分组以获得一组行,但是我很难将其转换为可以为每列选择第一个非空值的东西,然后把它变回一行(string[])。

理想情况下,我想要一个适用于任意数量列的函数,就像在实际文件中有很多列一样。

2 个答案:

答案 0 :(得分:1)

可以使用Aggregate使用LINQ来完成。创建一个函数,将运行总计与当前行进行比较,如果总计不为空且当前值,则将列的总计设置为列的当前值不是空的。

[TestMethod]
public void MergeArrays() {

    string[] Input = new[] { 
        "H1, H2, H3, H4",
        "1,2,,4",
        "1,,3,4"
    };


    var header = Input.ElementAt(0) ;
    var aggregation = string.Join(",", Input.Skip(1).Select(ln => ln.Split(',')).Aggregate(new[] { "", "", "", "" }, Agg));

    var result = new string[] { header, aggregation };


    Assert.AreEqual("H1, H2, H3, H4", header);
    Assert.AreEqual("1,2,3,4", aggregation);


}


private static string[] Agg(string[] aggregation, string[] input) {

    for (var idx = 0; idx < aggregation.GetLength(0); idx++) {
        if (aggregation[idx] == string.Empty &&input[idx] !=  string.Empty){
            aggregation[idx] = input[idx];
        }
    }

    return aggregation;

}

hth,
艾伦。

答案 1 :(得分:0)

  • 创建一个长度为4的数组,其值初始化为一些空字符串(或适当的零)。
  • 对于每个非标题行,循环遍历字段,只要字段值不为空,就将值存储在相应的数组位置。
  • 将数组中的值写出到新的CSV文件中。