2016-11-29 11 views
0

ファイルIはちょっとこのようになりCSVファイルを有する:(2列の各対は1つのデータセットに属するよう複数列のグループ化は、

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... 

ファイルの最初の行はヘッダを含み、どこ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()); 

どのように私はこれを達成することができますか?私は個々の行を失うことになるので、私はSelectMany()を使用することはできませんが、すべての行ではなく、各行の列をグループ化する必要があることをLINQに伝える方法が必要です(タプルの単一の列挙を取得しますタプルの列挙体の列挙体)

+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); 
    } 
} 
関連する問題