2017-06-09 4 views
0

私は数千行のテキストファイルを持っています。各行は、さまざまなテストの学生とテストのスコアです。すべての学生が同じ数のテスト(行)を持っているわけではありません。ファイルを小さな塊に分割する必要がありますが、私は学生の得点のグループを分割したくありません。メインファイルは既にソートされているので、ソートは必要ありませんが、ソートは適切な方法でソートします。テキストファイルから行を読み込み、値が一致すると行数を増やす

チャンクに少なくとも5行を追加したいとしますが、6行目が5行目と同じ生徒の場合は、チャンクに6行目を追加します。そして、学生が変わるまで続きます。

次に、元のファイルの末尾に達するまで、新しいチャンク(ヘッダーはありますが、その部分は簡単です)を開始します。

各チャンクを取得したら、linqまたはFileStreamのいずれかを使用しても問題はありません。これをAPI経由でアプリに読み込むことになります。ここで

がメインファイルの単純化されたサンプルです:だから

STUDENT_ID TEST SCORE 
000001   A  10 
000001   B  10 
000001   C  10 
000001   D  10 
000002   A  10 
000002   B  10 
000002   C  10 
000002   D  10 
000003   A  10 
000003   B  10 
000004   C  10 
000004   D  10 
000004   E  10 
000004   F  10 

、最初のチャンクは次のようになります。

STUDENT_ID TEST SCORE 
000001   A  10 
000001   B  10 
000001   C  10 
000001   D  10 
000002   A  10 
000002   B  10 
000002   C  10 
000002   D  10 

これまでのところ私は定数を使用してWhileループ1をやりました"rowsToTake" = 5、取得された5行目のSTUDENT_IDと各テイクで増分する「currentPosition」を比較する部分文字列(0、6)。私は外側のループで次のチャンクを得る勢いを失った。私はそれが良いとは思っていないので、私は今まで自分のコードを投稿しないようにしました。

答えて

0

私はLINQソリューションがあなたのシナリオに適しているとは思わない。私はそれに応じてテキストファイル内の各行の内容を比較して、forループを使用するほうがいいでしょう。


擬似コード:学生IDによってグループにLINQを使用して

string previousStudentID = null; 
List<...> chunk = new List<...>(); 
foreach (string line in file) 
{ 
    string studentID = // parse studentID from line 

    if (studentID != previousStudentID && chunk.Count > 5) 
    { 
     // add header to beginning of chunk 
     // load chunk to API 

     chunk.Clear(); // clear/create a new chunk 
    } 

    // add line to chunk 

    previousStudentID = studentID; 
} 

// load remaining header/chunk to API, if necessary 
+0

これは非常にうまくいく、単純であるというメリットがあり、メモリからAPIにデータをロードする作業をしています。私は@NetMageの答えを実行した後、最良の答えを選択します。ありがとう! – Jazzy

0

は非常に効率的ではないので、ライン中に処理した方が良いように見えました。

public class TestRecord { 
    public string line; 
    public string StudentID; 

    public TestRecord(string _line) { 
     line = _line; 
     StudentID = Regex.Split(line, @"\s+")[0]; 
    } 
} 

public IEnumerable<TestRecord> ReadRecords(string filename) { 
    var fileInput = File.ReadLines(filename); 

    foreach (var line in fileInput) 
     yield return new TestRecord(line); 
} 

void Main() { 
    var filePath = @"file folder\"; 
    var recordInput = ReadRecords($"{filePath}students.txt"); 
    var inputEnumerator = recordInput.GetEnumerator(); 

    // get header line 
    inputEnumerator.MoveNext(); 
    var headerLine = inputEnumerator.Current.line; 
    inputEnumerator.MoveNext(); 

    var chunkSize = 5; 

    var outFileCount = 0; 
    var chunkSoFar = 0; 
    StreamWriter outFile = null; 
    bool moreInput; 
    do { 
     if (chunkSoFar >= chunkSize || chunkSoFar == 0) { // start new chunk 
      outFile?.Close(); 
      outFile = new StreamWriter($"{filePath}chunk{++outFileCount:D4}.txt".Dump()); 
      outFile.WriteLine(headerLine.Dump()); 
      chunkSoFar = 0; 
     } 
     string curStudentID = inputEnumerator.Current.StudentID; 
     do { 
      outFile.WriteLine(inputEnumerator.Current.line.Dump()); 
      ++chunkSoFar; 
     } while ((moreInput = inputEnumerator.MoveNext()) && inputEnumerator.Current.StudentID == curStudentID); 
    } while (moreInput); 
    outFile.Close(); 
} 
関連する問題