2012-02-01 2 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

영원히 얼마나 오래 되었습니까? 얼마나 거대한 거죠? –

+0

각 csv 파일의 경우 약 300000 줄이며 완료하는 데 30m 이상 걸립니다. – fenec

+0

호스트의 RAM 용량은 얼마입니까? 라인이 얼마나 오래로드되고 있습니까? 코드가 실행되는 OS는 무엇입니까? –

답변

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

+0

큰 배열을 N 개의 더 작은 배열로 나눠서 마침내 문제를 해결했다. (버퍼를 사용하는 것과 같다.)이 과정에서 나는 빛의 속도에 도달했다. :) – fenec

+0

매우 근사합니다. 도움이 된 것을 기쁘게 생각합니다. –

1

당신이있어 gsub있는 File2마다은 File1을 통해 당신은 루프를 보내고. 나는 그것을 먼저하고, 그 결과를 비교해 볼 것입니다.

편집이 (테스트되지 않은) 같은 뭔가

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를하고 있습니까? 나는 스트립이 무엇을하고 있는지에 대해 gsubbing이 처리해야한다고 생각할 것이다. 스트립을 제거하면 조금 도움이 될 것입니다. –

관련 문제