2016-09-06 10 views
0

大規模なCSVからintsを読み込み、それらと特定の合計を行う必要があります。現在、私はアルゴリズムがありますjava read csv +サブアレイの特定の合計 - 最も効率的な方法

String csvFile = "D:/input.csv"; 
String line = ""; 
String cvsSplitBy = ";"; 
Vector<Int[]> converted = new Vector<Int[]>(); 

try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) { 

    while ((line = br.readLine()) != null) { 
     String[] a = line.split(";",-1); 
     int[] b = new int[a.length]; 
     for (int n = 0, n < a.length(), n++){ 
      b[n] = Integer.parseInt(a[n]); 
     } 
     converted.add(b); 
    } 
} 

catch (IOException e) { 
e.printStackTrace(); 
} 

int x = 7; 
int y = 5; 
int sum = 0;  

for (int m = 0; m < converted.size(); m++){ 
    for (n = 0, n < x, n++){ 
     sum = sum + converted.get(m)[n]; 
    } 
    System.out.print(sum + " "); 



    for (int n = x + y, n < converted.get(m).length, n = n + y){ 
     sum = 0; 
     for (int o = n -y; o < n; o++) 
     sum = sum + converted.get(m)[n]; 
     } 
     System.out.print(sum + " "); 
    } 
    System.out.println(""); 
} 

を私が実行しようとしました何を、すべての+ YをCSV行の最初のxメンバーの合計を取得した後、Xのメンバーの合計です。 (この場合、最初のx - 7の合計(0-6の合計)、次にx - 7の和、y - 5の列の後(5-11の合計)、(10-16の合計)... (最終的に最大(0-6の合計)、(5-11の合計)行番号を収集するので、最終的な結果は例えば5,9,13,155となるはずです。これは、5行目が0-6の最大合計、5行目の11行目の最大和を持つことを意味します)。わかりますように、これはかなり非効率的な方法です。まず、csv全体をstring [] int []に保存してVectorに保存しておけば、非常に非効率的なループが作成され、できるだけ早く実行する必要があります。私はたくさんの異なるxとyを持つ非常に大きなcsvを使用します。考えていたが、それを行う方法がわからないことは次のとおりです。

  1. は読み取りループ内でこれらの合計を行う
  2. は、xメンバーを常に逆方向にループしているわけではありません(最後の合計を保存して古いメンバーを減算し、新しいメンバーを追加するなど、サブアレイの合計を行う他の高速な方法)
  3. intStreamとparallelismを使用します私は最大を探しています)
  4. 異なる入力を使用してcsv?
  5. 上記のすべてですか?

これをできるだけ早く行うにはどうすればよいですか?ありがとうございました

答えて

1

合計が1行になるので、メモリ内のすべてを最初に読み取る必要はありません。

Path csvFile = Paths.get("D:/input.csv"); 
try (BufferedReader br = Files.newBufferedReader(csvFile, StandardCharsets.ISO_8859_1)) { 

    String line; 
    while ((line = br.readLine()) != null) { 
     int[] b = lineToInts(line); 
     int n = b.length; 

     // Sum while reading: 
     int sum = 0; 
     for (int i = 0; i < 7; ++i) { 
      sum += b[i]; 
     } 
     System.out.print(sum + " "); 

     sum = 0; 
     for (int i = n - 5; i < n; ++i) { 
      sum += b[i]; 
     } 
     System.out.print(sum + " "); 

     System.out.println(); 
    } 
} 

private static int[] lineToInts(String line) { 
    // Using split is slow, one could optimize the implementation. 
    String[] a = line.split(";", -1); 
    int[] b = new int[a.length]; 
    for (int n = 0, n < a.length(), n++){ 
     b[n] = Integer.parseInt(a[n]); 
    } 
    return b; 
} 

速いバージョン:余談として

private static int[] lineToInts(String line) { 
    int semicolons = 0; 
    for (int i = 0; (i = line.indexOf(';', i)) != -1; ++i) { 
     ++semicolons; 
    } 
    int[] b = new int[semicolons + 1]; 
    int pos = 0; 
    for (int i = 0; i < b.length(); ++i) { 
     int pos2 = line.indexOf(';', pos); 
     if (pos2 < 0) { 
      pos2 = line.length(); 
     } 
     b[i] = Integer.parseInt(line.substring(pos, pos2)); 
     pos = pos2 + 1; 
    } 
    return b; 
} 

:ベクトルが古い、よりよい使用リストとのArrayList。

List<int[]> converted = new ArrayList<>(10_000); 

上記の初期容量のオプションの引数は、以下のとおりです。

奇妙なtry-with-resource構文try (BufferedReader br = ...) {は、常にbrが常に自動的に閉じられることを保証します。例外や返品の場合でも。


並列処理や質問

を再フォーマットした後、あなたはすべての行

List<String> lines = Files.readAllLines(csvFile, StandardCharsets.ISO_8859_1); 

など並列ストリームと遊ぶよりも読むことができる:

OptionalInt max = lines.parallelStream() 
    .mapToInt(line -> { 
     int[] b = lineToInst(line); 
     ... 
     return sum; 
    }).max(); 

Oをr:

IntStream.range(0, lines.size()).parallel() 
    .mapToObj(i -> { 
     String line = lines.get(i); 
     ... 
     return new int[] { i, sum5, sum7 }; 
    }); 
+0

ありがとうございます、私はそれを試して速度を比較します。ここでは2番目の合計(n-5)の発言だけで、最初の7と最後の5の合計は必要ありませんが、私は7人のメンバーの合計が5で移動する必要があります。1合計は最初の7の和です0〜6)、2番目は7の合計でなければなりませんが、配列pos 5〜11、次に10〜16 ...のように5で移動しますが、まだ7つのメンバーの合計です。過去7日間、5日ごとの合計(最初の合計は7日後に行うことができますが、その後は5回) ベクトルに関しては、arraylistはスレッドセーフではなく、並列性を追加することを望んでいたので、 – user3338991

+0

合計はちょっと眩しいですが、それほど難しくありませんか?ディスクからの読み取りと計算は、最初の読み取りと計算よりも速くなります。特に、データが完全にメモリ内にある場合は、計算が高速です。しかし、私はいくつかの並列性を追加します。 –

0

おそらく入力を読みながらいくつかの合計を作成しようとする可能性があります。 Integer、Integer型のHashMapsを使用することも可能です。

関連する問題