2012-02-01 13 views
1

は、ここに私のコードですが、それは巨大なファイルのために永遠に取る:2つのCSVファイルで同様の行を見つけるにはどうすればよいですか?

require 'rubygems' 
require "faster_csv" 

fname1 =ARGV[0] 
fname2 =ARGV[1] 
if ARGV.size!=2 
    puts "Display common lines in the two files \n Usage : ruby user_in_both_files.rb <file1> <file2> " 
    exit 0 
end 

puts "loading the CSV files ..." 
file1=FasterCSV.read(fname1, :headers => :first_row) 
file2=FasterCSV.read(fname2, :headers => :first_row) 
puts "CSV files loaded" 

#puts file2[219808].to_s.strip.gsub(/\s+/,'') 

lineN1=0 
lineN2=0 
# count how many common lines 
similarLines=0 
file1.each do |line1| 
    lineN1=lineN1+1 
    #compare line 1 to all line from file 2 
    lineN2=0 
    file2.each do |line2| 
     puts "file1:l#{lineN1}|file2:l#{lineN2}" 
     lineN2=lineN2+1 
     if (line1.to_s.strip.gsub(/\s+/,'') == line2.to_s.strip.gsub(/\s+/,'')) 
      puts "file1:l#{line1}|file2:l#{line2}->#{line1}\n" 
      similarLines=similarLines+1 
     end 
    end 
end 
puts "#{similarLines} similar lines." 
+0

永遠にどれくらいですか?どのくらい巨大ですか? –

+0

各csvファイルに約300000行あり、完了に30m以上かかる – fenec

+0

あなたのホストにはどのくらいのRAMがありますか?どのくらいの時間、ラインがロードされていますか?コードはどのOSで動作していますか? –

答えて

2

Rubyが配列で利用可能な操作を設定しました:

a_ary = [1,2,3] 
b_ary = [3,4,5] 
a_ary & b_ary # => 3 

だから、あなたは試してみてくださいそれから:あなたがそれらをロードするよう

puts "loading the CSV files ..." 
file1 = FasterCSV.read(fname1, :headers => :first_row) 
file2 = FasterCSV.read(fname2, :headers => :first_row) 
puts "CSV files loaded" 

common_lines = file1 & file2 
puts common_lines.size 

を使用すると、前処理に配列が必要な場合は、それを実行します。

file1 = FasterCSV.read(fname1, :headers => :first_row).map{ |l| l.to_s.strip.gsub(/\s+/, '') } 
file2 = FasterCSV.read(fname2, :headers => :first_row).map{ |l| l.to_s.strip.gsub(/\s+/, '') } 
+0

私はあなたの指示に従っていますが、非常に遅いです。私は本当に遅いです。 – fenec

+0

最後に大きな配列をN個の小さな配列に分割することで問題を解決しました。 :) – fenec

+0

非常にクールです。私はそれが助けてうれしいです。 –

1

あなただgsub File2のたびはFile1を通してあなたがループをINGの。私はまずそれを行い、その結果を比較するだけです。

編集(未テスト)このような何か

file1lines = [] 
file1.each do |line1| 
    file1lines = line1.strip.gsub(/\s+/, '') 
end 

# Do the same for `file2lines` 

file1lines.each do |line1|  
    lineN1=lineN1+1  
    #compare line 1 to all line from file 2  
    lineN2=0  
    file2lines.each do |line2|  
    puts "file1:l#{lineN1}|file2:l#{lineN2}"  
    lineN2=lineN2+1  
    if (line1 == line2)  
     puts "file1:l#{line1}|file2:l#{line2}->#{line1}\n"  
     similarLines=similarLines+1  
    end  
    end  
end  

あなたが本当にそれらを必要としない限り、私はまた、ループ内のすべてのputsのESを取り除くと思います。ファイルが巨大であれば、おそらくそれは目立つ量を減速させるでしょう。

+0

ありがとう、半分の時間を切っていますが、まだ20mくらいです。 – fenec

+0

lineN1とlineN2を取り除くことができます。あなたは私が見ることができるものから、それらと何もしないことから、それらを増やしています。おそらくあなたのスピードはそれほど向上しません。 –

+1

別の質問:なぜあなたはストリップをやって、GSub?私はストリップが何をしているのか世話するべきだと思うだろう。ストリップを取り外すと少しでも役立ちます。 –

関連する問題