大量のCSVファイルのデータをソート(sort:並べ替え)するのは、本来はデータベース側で行うことであって、rubyで行うことではありません。しかし、実際にはrubyで行うことになる場合もあります。そうした場合にrubyでどのような対応を行うかについて説明していきます。ここで大量のCSVファイルとは、[2-4-2.CSVファイルの文字列型昇順ソート]で並べ替える場合は100万件以上、[2-4-3.CSVファイルの文字列型・数値型/昇順・降順ソート(その1)]で並べ替える場合は10万件以上のCSVデータが1つのファイルに入っていることを前提にしています。これ以上のデータを並べ替える(ソートする)には以下の手順で行います。
まず、並べ替えの方式のどれかを確認します。
1の場合は、以下の手順で行います。
2の場合は、以下の手順で行います。
実際に応用する場合は、入出力データのファイル名を変更し、「sortitem = [1,0]」の部分を変更します。この例では、2番目の項目を第1キーとし、1番目の項目を第2キーとして並べ替えるように指定しています。rubyでは、配列のインデックスは「0」から開始されますので、1番目の項目を「0」、2番目の項目を「1」として指定することに注意してください。
下記の例では、フィールドを「"」(ダブルクォーテーションつき)で囲み、それぞれのデータを「,」(カンマ)で区切っている形式を前提としているため、
in1 = (line1 + ',')
.scan(/"([^"\\]*(?:\\.[^"\\]*)*)",|([^,]*),/)
.collect{|x,y| y || x.gsub(/(.)/, '\1')}
としていますが、フィールドを「"」(ダブルクォーテーションつき)で囲まずに、それぞれのデータを「,」(カンマ)で区切っている、いわゆる「CSV2形式」であれば、以下のようにすることができます。
in1 = line1.split(",",-1)
また、タブ区切りであれば、以下のようにすることができます。
in1 = line1.split("\t",-1)
# keycount.rb
# 内容 :CSV形式のファイルのソートキーごとの件数と累計件数をカウントする。
# Copyright (c) 2011-2015 Mitsuo Minagawa, All rights reserved.
# (minagawa@fb3.so-net.ne.jp)
# 使用方法 : c:\>ruby keycount.rb
#
# 入力ファイル
in1_file = open("input.txt","r")
# 出力ファイル
out1_file = open("output.txt","w")
# 整列の基準となる項目番号
# ソートキー
sortitem = [1,0]
# ソートキーをセットする配列
hash_key = nil
# ソートするレコードをセットするハッシュ
sort_rec = Hash.new
# 累計件数
total_ctr = 0
# ソートキーとなる項目番号からソートキーとなる文字列を作っておく
while (line1 = in1_file.gets)
line1.chomp!
# CSVファイルを各項目に分解する
in1 = (line1 + ',')
.scan(/"([^"\\]*(?:\\.[^"\\]*)*)",|([^,]*),/)
.collect{|x,y| y || x.gsub(/(.)/, '\1')}
# タブ区切りファイルを各項目に分解する
# in1 = line1.split("\t",-1)
# 整列の基準となる項目番号の項目内容をタブ値ではさんで連結してキーとする
hash_key = ""
sortitem.each {|i|
hash_key += in1[i] + "\t"
}
hash_key.chop!
# ソートキーに該当するキーがあれば、件数を加算する。
if (sort_rec.include?(hash_key))
sort_rec[hash_key] += 1
# 新たなソートキーに該当する場合は、初期値1をセットする。
else
sort_rec[hash_key] = 1
end
hash_key = nil
end
# ハッシュのキーをソートし、キー順にレコードを出力する
#sort_rec.sort{|a,b| a[0] <=> b[0]}.each{|key,value|
sort_rec.sort_by{|key| key }.each{|key,value|
total_ctr += value
out1 = [key,value,total_ctr].join("\t")
out1_file.print out1,"\n"
}
# ファイルのクローズ
in1_file.close
out1_file.close
ccc,5555
aaa,7777
bbb,9999
aaa,1111
bbb,3333
bbb,4444
aaa,5555
ccc,1111
aaa 3 3 bbb 3 6 ccc 2 8