2017-07-14 14 views
0

私は脚本から短いラインの非常に巨大なjsonファイルを持っています。私はjsonファイル内のキーワードにキーワードを一致させようとしているので、jsonからの行を引き出すことができます。大規模なjsonでのルビーの検索

[ 
"Yeah, well I wasn't looking for a long term relationship. I was on TV. ", 
"Ok, yeah, you guys got to put a negative spin on everything. ", 
"No no I'm not ready, things are starting to happen. ", 
"Ok, it's forgotten. ", 
"Yeah, ok. ", 
"Hey hey, whoa come on give me a hug... " 
] 

(合計に加えて、より多くの... 2444ライン)

は、これまでのところ、私はこれを持っているが、それはどんな試合をしていないです:

JSONファイル構造は次のようです。

# screenplay is read in from a json file 
@screenplay_lines = JSON.parse(@jsonfile.read) 
@text_to_find = ["relationship","negative","hug"] 

@matching_results = [] 
@screenplay_lines.each do |line| 
    if line.match(Regexp.union(@text_to_find)) 
    @matching_results << line 
    end 
end 

puts "found #{@matching_results.length} matches..." 
puts @matching_results 

私が働いていないものをそれほどわからない任意のヒットが届きません。さらに、大量のデータでこのように処理するのは非常に高価なプロセスだと私は確信しています。何か案は?ありがとう。

答えて

1

はい、正規表現のマッチングは、文字列をテキストの行に含まれている場合だけチェックするよりも遅くなります。しかし、これはキーワードの数や行の長さなどにもよります。したがって、少なくともマイクロベンチマークを実行するのが最善です。この設定で

lines = [ 
"Yeah, well I wasn't looking for a long term relationship. I was on TV. ", 
"Ok, yeah, you guys got to put a negative spin on everything. ", 
"No no I'm not ready, things are starting to happen. ", 
"Ok, it's forgotten. ", 
"Yeah, ok. ", 
"Hey hey, whoa come on give me a hug... " 
] 
keywords = ["relationship","negative","hug"] 


def find1(lines, keywords) 
    regexp = Regexp.union(keywords) 

    lines.select { |line| regexp.match(line) } 
end 


def find2(lines, keywords) 
    lines.select { |line| keywords.any? { |keyword| line.include?(keyword) } } 
end 

def find3(lines, keywords) 
    regexp = Regexp.union(keywords) 

    lines.select { |line| regexp.match?(line) } 
end 

require 'benchmark/ips' 

Benchmark.ips do |x| 
    x.compare! 
    x.report('match') { find1(lines, keywords) } 
    x.report('include?') { find2(lines, keywords) } 
    x.report('match?') { find3(lines, keywords) } 
end 

include?バリアントは道高速です:

Comparison: 
      include?: 288083.4 i/s 
       match?: 91505.7 i/s - 3.15x slower 
       match: 65866.7 i/s - 4.37x slower 

ご注意:

  • を私はループの外に正規表現の作成を移動しました。すべての行に作成する必要はありません。正規表現の作成は高価な操作です(ループ外の正規表現の1/5の速度で実行されるバリアント)
  • match?はRuby 2.4以降でのみ使用可能ですが、一致しないため結果(副作用なし)

2500行のテキストのパフォーマンスについては心配しません。それが十分に速ければ、より良い解決策を探すのをやめてください。

+0

ありがとうございます。素晴らしい洞察find1()メソッドは正常に動作しています – matski

0

可能な解決策があり、これを試してみてください:

json_expressions

+0

おかげさまで、面白そうですが、第三者の宝石に頼る前に、少ないコードで解決できるかどうか確認したいと思います。 – matski

関連する問題