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