2012-02-01 83 views
1

這裏是我的代碼,但它永遠花費巨大的文件:如何在兩個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

永遠有多久?巨大的巨大? – 2012-02-01 19:20:26

+0

每個csv文件大約需要300000行,並且需要超過30m才能完成 – fenec 2012-02-01 19:22:34

+0

主機上有多少RAM?這些行被加載了多長時間?運行的代碼是什麼操作系統? – 2012-02-01 21:01:51

回答

2

紅寶石已設置的可用操作使用數組:

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 2012-02-01 20:42:21

+0

我終於通過將大陣列分成N個更小的陣列(它像使用緩衝區)來解決這個問題,這個過程我達到了光速。 :) – fenec 2012-02-02 16:04:58

+0

非常酷。我很高興它有幫助。 – 2012-02-02 21:21:53

1

gsub每次遍歷文件1荷蘭國際集團文件2。我會先做,然後比較結果。

編輯像這樣(未經)

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

非常感謝你,它正在減少一半的時間,但它仍然需要20米 – fenec 2012-02-01 19:25:15

+0

你可以嘗試擺脫lineN1和lineN2。你正在增加它們,從我所能看到的,沒有對它們做任何事情。這可能不會提高你的速度太多。 – 2012-02-01 19:28:13

+1

另一個問題:你爲什麼要做這個地帶,然後是GSub?我認爲gsubbing的\ s應該照顧什麼帶正在做。去除條帶會有所幫助。 – 2012-02-01 19:28:55

相關問題