[英]ruby: how to iterate elements in a hash efficiently
我有一个很大的哈希,我想对其进行迭代。 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@;"}
考虑以下示例,该示例使用一百万个元素的哈希值:
#! /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.16秒,散列为0.35秒)。 但是生成阵列花费了0.3秒。 因此,净过程比0.35秒慢了0.46秒。
因此看来,至少在此测试案例中,最好仅遍历哈希。
在ruby中,更惯用的方法是:
record = name_hash.map{|k,v| "#{k}|#{v}"}.join("\n")
我不知道如何将它与速度进行比较,但是部分问题可能是因为您不断在字符串上添加一些内容,并且每次迭代都创建新的(更长的)字符串对象。 联接是用C语言完成的,可能会更好。
String#+
很慢。 这应该改善它
record = name_hash.map{|line| line.join("|")}.join("\n")
如果使用此方法输出到某个地方,则不应创建巨大的字符串,而应逐行写入输出。
对大型集合进行迭代很慢,每种方法都无法解决问题。 您在循环中执行的操作是如此缓慢? 如果需要转换为数组,可以通过调用some_hash.to_a
将大型哈希转换为数组将需要创建一个大型对象,并且将需要进行两次迭代,尽管其中之一在解释器内部并且可能非常快。
这不可能比仅在Hash上迭代要快,但可能适用于大型对象。
请查看标准库基准测试包 ,以方便地测量运行时间。
我也敢冒险猜测,这里的真正问题是您有一个类似于Hash的ActiveRecord对象,该对象在枚举的每个循环中都强制往返数据库服务器。 这有可能是你真正想要的是绕过AR和运行本机查询到在一个往返一次获取的一切。
我以为ruby 1.9.x可以使哈希迭代更快,但可能是错误的。 如果是简单的结构,则可以尝试使用其他哈希,例如https://github.com/rdp/google_hash ,这是我为提高#each的可靠性而特意破解的哈希...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.