繁体   English   中英

红宝石:如何有效地迭代哈希中的元素

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM