2016-11-29 47 views
0

我有一个CSV文件,它有点看起来像这样:多列分组文件

Header1a; Header1b; Header2a; Header2b; Header3a... 
Value1a; Value1b; Value2a; Value2b; Value3a... 
Value1a; Value2b; Value2a; Value2b; Value3a... 
Value1a; Value2b; Value2a; Value2b; Value3a... 
Value1a; Value2b; Value2a; Value2b; Value3a... 

该文件的第一行包含标头,其中,每对2列属于一个数据组( Header1,Header2, Header3)。这同样适用于实际值:Value1aValue1b是属于Header1值的元组等等...

所以:

Set 1 (Header 1) | Set 2 (Header 2) | Set 3 (Header 3) | 
----------------------------------------------------------- 
Value1a, Value1b | Value2a, Value2b | Value3a, Value3b | <-- tuples 
Value1a, Value1b | Value2a, Value2b | Value3a, Value3b | 
Value1a, Value1b | Value2a, Value2b | Value3a, Value3b | 
Value1a, Value1b | Value2a, Value2b | Value3a, Value3b | 

我试图做到的,是创建一个类型对于每个数据集有一个头和一个元组列表表示该组的值。

class DataSet { 
    string Name; 
    List<Tuple<string, string>>() 
} 

我的方法,到目前为止是让CSV文件的第一行,用隔板分开它(;),并采取从每2项显示的文本数组中,得到数据集的名称以及文件中数据集的数量。

var headers = firstLine.Split(new[] { separator } 
       .Where((header, index) => index % 2 == 0)) 
       -> cleanup (Header1a => Header1) etc.. 

,然后使用分组处理行的其余部分:

// total amount of columns per row 
var columnCount = headers.Count * 2; 
var values = rows 
    // split the rows using the separator (;) 
    .Select(row => row.Split(new[] { separator }) 
    // take only those rows which fit the column count (=> headers) 
    .Where(columns => columns.Length == columnCount) 
    // select the columns by index 
    .Select((columns, index) => new { columns, index }) 

    // now here I want to group the columns of each row into groups of 2 columns 
    // but that doesn't actually work, it groups the total amount of rows 
    // by groups of 2 rows each 
    .GroupBy(group => group.index/2, group => group.columns) 
    .Select(group => group.ToArray()); 

我怎样才能做到这一点?我需要一些方法来告诉LINQ它应该将每行的列分组,而不是遍及所有行,但是我不能使用SelectMany(),否则我会丢失单个行(我将得到单个元组枚举,而不是枚举元组枚举。)

+1

如果你真的想使用LINQ的这个创建帮助方法为每行返回对。使用linq中的约定循环编写起来要容易得多。我非常喜欢linq,但人们经常在不打算去的地方使用它。 – jdweng

回答

1

试过了一个可能有帮助的代码示例。

首先创建一些样本数据,我们可以为源使用:

List<String> data; 
{ 
    var rows = Enumerable.Range(1, 10); 
    var sets = Enumerable.Range(1, 6); 
    var itemsPerSet = Enumerable.Range(1, 2); 

    data = rows.Select(rowIndex => 
     String.Join(Environment.NewLine, 
      String.Join(",", sets.Select(setIndex => 
       String.Join(",", itemsPerSet.Select(itemIndex => 
        $"Value{rowIndex}-{setIndex}-{itemIndex}")))))).ToList(); 

    foreach (var row in data) 
    { 
     Console.WriteLine(row); 
    } 

    Console.WriteLine(new String('-', 20)); 
} 

然后获取所需的数据出来吧:

var selectedColumns = new[] { 0, 1, 4, 5 }; 

var foo = data.Select(row => row.Split(new[] { "," }, StringSplitOptions.None) 
           .Where((value, columnIndex) => selectedColumns.Contains(columnIndex))) 
       .Select(row => row.Select((Value, ColumnIndex) => new { Value, ColumnIndex }) 
           .GroupBy(pair => pair.ColumnIndex/2) 
           .Select(group => $"Group{group.Key}({String.Join(";", group.Select(pair => pair.Value))})")); 

foreach (var row in foo) 
{ 
    foreach (var item in row) 
    { 
     Console.WriteLine(item); 
    } 
}