2009-07-07 9 views
1

私はopencsvライブラリを使って処理しているCSVファイルを持っています。だから私は各行で読むことができます。私が行う必要がある特定の変換では、私がJavaファイルの主要部分を実行する前に、まずそのファイルをソートする必要があります。Javaでtxtファイルをソートする最適な方法

私はこれを実行する必要が

5423, blah2, blah 
5323, blah3, blah 
5423, blah4, blah 
5444, blah5, blah 
5423, blah6, blah 

5323, blah3, blah 
5423, blah2, blah 
5423, blah4, blah 
5423, blah6, blah 
5444, blah5, blah 

などになる必要があります。..

理由は、私は同じIDを持つすべての行を組み合わせて、新しいファイルに出力しています。

に何か問題:

  1. opencsvライブラリでcsvファイルの各行を読む

  2. この

    にソートのいくつかの並べ替えを実行して2次元配列に

  3. それらを追加します。

  4. ソートされた配列をループしてファイルに出力します。

データのソートには他にどのようなアイデアがありますか?

Javaでビットが錆びます。

UPDATE: それは次のようになり、最終的な出力

に明確にする:これは私がやっているのは非常に単純化したバージョンである

5323, blah3, blah 
5423, blah2!!blah4!!blah6, blah 
5444, blah5, blah 

。実際には、JBaseシステムの複数のオプションフィールドに必要です。これは要求されたファイル形式です。

元のファイルには100,000以上の行があります。

これは2回以上実行され、実行される速度は私にとって重要です。

+1

なぜ単なる次元配列ではないのですか? – Peter

+0

@Peter 2番目の次元は行の内容だと思います。しかし、私はそれが行オブジェクトの1次元配列(特にComparatorの実装を見ているとき)と考える方が簡単であることに同意します。 –

+0

コマンドラインでこれを行いますか?あるいはこれをプログラム的にやりたいのですか?また、すべてをメモリに読み込み可能になっていますか?または、これをスケーラブルにして、非常に大きなファイルをサポートしたいですか? – Tom

答えて

5

最新のリクエストを達成するには、GoogleのコレクションでMultimapを使用することを強くおすすめします。あなたのラインエンダーとして"blah\n"使用する必要が

CSVReader reader = ...; 
CSVWriter writer = ...; 

Multimap<String, String> results = TreeMultimap.create(); 

// read the file 
String[] line; 
for ((line = reader.readNext()) != null) { 
    results.put(line[0], line[1]); 
} 

// output the file 
Map<String, Collection<String>> mapView = results.asMap(); 
for (Map.Entry<String, Collection<String> entry : mapView.entries()) { 
    String[] nextLine = new String[2]; 
    nextLine[0] = entry.getKey(); 
    nextLine[1] = formatCollection(entry.getValue()); 
    writer.writeNext(nextLine); 
} 

:あなたのコードは次のようになります。スピードを気にするが、エントリーを並べ替えるのではなく、HashMultimapと同様にベンチマークする必要があります。

私の前の回答

最もstraightford方法は、* nixのでsortコマンドを使用することです(例えば、LinuxおよびMac OS)は、

sort -n myfile.csv 

のようにWindowsは、同様sortコマンドを持っていますが、(すなわち、5 'は' '13、」行)の前に置かれるアルファベット順に行をソートします。

ただし、推奨される解決策に間違いはありません。配列を作成してソートする代わりに、TreeSetを使用することもできます。

EDIT:Windowsについてのメモを追加します。

+0

+1ソートコマンドコールのアプローチが好きです。 – ATorras

+1

+1 TreeSet。 SortedSetでもかまいません。 – Tom

+1

SortedSetはインターフェイスです。 TreeSetは実装です! Collections APIには、一般的に知られていない、または残念ながら使用されていないいくつかの宝石があります。 – notnoop

1

Collections.sort()Comparatorインスタンスを試しましたか?

+0

ソートは最終目標にとって不要です。 – Tom

+0

もちろん、質問の「この種の並べ替えを実行する」という部分を除いて。 – Tom

+1

ああああ... 2人のトムは混乱するだろう: - P。他のトム:私はOPのソート方法を尋ねたが、彼はまた、彼がやろうとしていることを説明し、他のアイデアを尋ねた...私はO(nlogn) )ソリューションはそのカテゴリに入ります:-)。技術的に正解で、質問の一部に答えているので、私はこの回答を-1しなかった。しかし、OPが極端に小さいデータセットを扱っていない限り、最も良い解決策ではない可能性が高いので、私はそれを+1しませんでした。 – Tom

0

単一次元のArrayList(または他のコレクション)を使用して、コレクションのソート方法を使用してJavaで並べ替えることができます。あなたが説明したすべてのものはかなり標準的に聞こえる。

+0

ソートは最終目標にとって不要です。 – Tom

0

あなたはアイテムを「並べ替える」必要があると言いますが、あなたの説明はグループのように聞こえます。これは多くの方法で行うことができます。 google collectionsによって提供されるようなマルチマップを調べることができます。

HashMap<Long, List<String>> 

を作成して、各行を読んでから適切なリストに配置するだけで済みます。このような場合の私の好みは、ファイルを2回通し、各キーに新しいArrayListを追加するため、そして各文字列をリストに追加するための2回目のパスですが、単一パスを使用する方が効率的ですリストが既に地図にあるかどうかをチェックします。

0

全体をソートする必要はありません。私はあなたが持っている行数は分かりませんが、何らかのハッシュベースのスキームを使うことができるようです。ファイルをハッシュマップでバケツと考えることができ、各行を読み終えたら、そのファイルがどのファイルに属するのかを判断します。次に、各ファイルをさらに処理することができます。あなたがこれを行うには、いくつかの方法があります。あなたは、「キー」の多くを持ってない場合は

  • 、あなたは実際には単なる文字列のハッシュマップにキーとしてファイル名にキーをマップする=>の文字列(マップをメモリ内のすべてのキーを保つことができますその行が属する)。

  • メモリに保存するキーが多すぎる場合。ファイルのサイズを小さくするのに役立つように、行を別のファイルにバケットしようとすることができます。その後、各ファイルをメモリに保存することができます。これにより、行をコレクションにダンプして並べ替えることができます。あるいは、おそらく私が言及した最初のスキームを使用します。

これは意味がありますか?あなたが混乱していると、私はおそらくもっと詳しく説明することができます。私はあなたのキーが何とかあなたのCSVラインのすべての列を組み合わせて作られると思います。

このアプローチは、ファイルが非常に大きくなった場合に、よりスケーラビリティが向上します。理論的には、ハッシング・スキームはただO(n)ですが、ソートにはO(nlogn)時間がかかります。

0

FlatPackは、そのようなファイルを読み込んで並べ替えるのに最適です。また、データセットをファイルにエクスポートするオプションもあります。あなたは、IDのソートにのみ関心がある、とそのID内の順序について気にされていない場合は

1

、あなたは単にTreeMapのとコモンズコレクションからMultiValueMapを組み合わせることができます

MultiValueMap m = MultiValueMap.decorate(new TreeMap()); 

m.put(2, "B"); 
m.put(3, "Y"); 
m.put(1, "F"); 
m.put(1, "E"); 
m.put(2, "K"); 
m.put(4, "Q"); 
m.put(3, "I"); 
m.put(1, "X"); 

for(Iterator iter = m.entrySet().iterator(); iter.hasNext();) { 
    final Map.Entry entry = (Map.Entry)iter.next(); 
    System.out.println(entry.getKey() + ": " + entry.getValue()); 
} 

をこれが与え実行します:

1: [F, E, X] 
2: [B, K] 
3: [Y, I] 
4: [Q] 

MultiValueMapで使用するコレクションタイプを指定できるオーバーロードされたデコレートメソッドがあります。 ID内でソートする必要がある場合は、これで何かできます。

関連する問題