1

私は非常に大きなハッシュを持っており、それを繰り返したいと思っています。Hash.each遅すぎるようです。これを行う効率的な方法はありますか?

このハッシュを配列に変換するのはどうですか?


各ループでは、非常に単純な文字列の処理を行っています。

name_hash.each {|name, str|

  record += name.to_s + "\|" + str +"\n"

}

ハッシュは人の名前をキーとして使用し、関連するコンテンツを値として使用します。

name_hash = {:"jose garcia" => "ca:tw#2@1,2@:th#1@3@;ar:tw#1@4@:fi#1@5@;ny:tw#1@6@;"}
4

6 に答える 6

4

100 万要素のハッシュを使用する次の例を考えてみましょう。

#! /usr/bin/env ruby
require 'benchmark'

h = {}
1_000_000.times do |n|
  h[n] = rand
end

puts Benchmark.measure { h.each { |k, v| } }

a = nil
puts Benchmark.measure { a = h.to_a }
puts Benchmark.measure { a.each { |k, v| } }

これを職場のシステム (Ruby 1.8.5 を実行) で実行すると、次のようになります。

  0.350000   0.020000   0.370000 (  0.380571)
  0.300000   0.020000   0.320000 (  0.307207)
  0.160000   0.040000   0.200000 (  0.198388)

そのため、配列の反復処理は確かに高速です (ハッシュの 0.35 秒に対して 0.16 秒)。しかし、配列の生成には 0.3 秒かかりました。したがって、正味のプロセスは 0.35 秒に対して 0.46 秒遅くなります。

したがって、少なくともこのテストケースでは、ハッシュを反復処理するのが最善のようです。

于 2012-08-15T23:18:29.313 に答える
2

String#+遅い。これはそれを改善するはずです

 record = name_hash.map{|line| line.join("|")}.join("\n")

これを使用してどこかに出力する場合は、巨大な文字列を作成するのではなく、出力に1行ずつ書き込む必要があります。

于 2012-08-15T23:52:32.880 に答える
2

Rubyでそれを行うより慣用的な方法:

record = name_hash.map{|k,v| "#{k}|#{v}"}.join("\n")

それが速度とどのように比較されるかはわかりませんが、問題の一部は、文字列に少しずつ追加し続け、反復ごとに新しい (より長い) 文字列オブジェクトを作成し続けることが原因である可能性があります。結合は C で行われ、パフォーマンスが向上する可能性があります。

于 2012-08-15T23:51:24.700 に答える
1

大きなコレクションの繰り返しは遅く、各メソッドはそれを調整していません。あなたのループの中で、とても遅いのは何ですか? 配列に変換する必要がある場合は、呼び出して行うことができますsome_hash.to_a

于 2012-08-15T22:50:13.020 に答える
1

おそらく「単一のデータベースクエリを作成することによって」

大きなハッシュを配列に変換するには、大きなオブジェクトを作成する必要があり、2 回の反復が必要になりますが、そのうちの 1 つはインタープリターの内部にあり、おそらく非常に高速です。

これは、ハッシュを反復処理するよりも高速になる可能性は低いですが、大きなオブジェクトの場合にはそうなる可能性があります。

ランタイムを測定する簡単な方法については、Standard Library Benchmark パッケージを確認してください。

また、ここでの本当の問題は、列挙の各サイクルでdb サーバーへのラウンドトリップを課すハッシュのような ActiveRecord オブジェクトがあることだと思います。AR をバイパスしてネイティブ クエリを実行し、 1回の往復で一度にすべてを取得することが本当に必要な場合があります。

于 2012-08-15T23:08:00.200 に答える
1

ruby 1.9.x でハッシュの繰り返しが速くなったと思っていたのですが、それは間違っていた可能性があります。単純な構造の場合は、https://github.com/rdp/google_hashのように別のハッシュを試すことができます。これは #each をより信頼性の高いものにするためにハッキングしたものです...

于 2012-08-15T23:16:37.317 に答える