Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails ruby:如何高效地迭代散列中的元素_Ruby On Rails_Ruby_Arrays_Hash - Fatal编程技术网

Ruby on rails ruby:如何高效地迭代散列中的元素

Ruby on rails ruby:如何高效地迭代散列中的元素,ruby-on-rails,ruby,arrays,hash,Ruby On Rails,Ruby,Arrays,Hash,我有一个非常大的散列,我想迭代它。散列。每个看起来都太慢了。 有什么有效的方法可以做到这一点吗 把这个散列转换成数组怎么样 在每个循环中,我都在做非常简单的字符串工作: 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#

我有一个非常大的散列,我想迭代它。散列。每个看起来都太慢了。 有什么有效的方法可以做到这一点吗

把这个散列转换成数组怎么样

在每个循环中,我都在做非常简单的字符串工作:

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@;"}

迭代大型集合的速度很慢,每个方法都不是限制它的因素。你在做什么,这么慢?如果需要转换为数组,可以通过调用一些散列来实现。要想在大型集合上迭代很慢,each方法并不是限制它的方法。你在做什么,这么慢?如果您需要转换为数组,您可以通过调用一些\u hash.to\u a

来实现这一点,可能需要进行单个db查询 将大型散列转换为数组需要创建一个大型对象,并且需要两次迭代,尽管其中一次迭代是解释器内部的,并且可能非常快

这不太可能比在散列上迭代更快,但对于大型对象可能更快

查看一个测量运行时的简单方法

我还想大胆猜测,这里真正的问题是,您有一个类似于哈希的ActiveRecord对象,它在枚举的每个周期中对db服务器施加一个往返。您真正想要的可能是绕过AR并运行本机查询,以便在一次往返中一次检索所有内容。

可能是通过进行一次db查询 将大型散列转换为数组需要创建一个大型对象,并且需要两次迭代,尽管其中一次迭代是解释器内部的,并且可能非常快

这不太可能比在散列上迭代更快,但对于大型对象可能更快

查看一个测量运行时的简单方法


我还想大胆猜测,这里真正的问题是,您有一个类似于哈希的ActiveRecord对象,它在枚举的每个周期中对db服务器施加一个往返。您真正想要的可能是绕过AR,运行一个本机查询,在一次往返中一次检索所有内容。

我原以为ruby 1.9.x加快了哈希迭代,但可能是错误的。如果是简单的结构,你可以尝试一个不同的散列,就像我为了使每一个更可靠而破解的一样…

我原以为ruby 1.9.x使散列迭代更快,但可能是错的。如果是简单的结构,你可以尝试不同的散列,比如我为了使每个散列更可靠而对其进行了黑客攻击…

考虑以下示例,该示例使用了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.16秒,而散列的速度要快0.35秒。但生成阵列需要0.3秒。因此,净过程比0.35秒慢0.46秒


因此,至少在本测试用例中,似乎最好只对哈希进行迭代。

考虑以下示例,该示例使用了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.16秒,而散列的速度要快0.35秒。但生成阵列需要0.3秒。因此,净过程比0.35秒慢0.46秒


因此,至少在这个测试用例中,似乎最好只对散列进行迭代。

在ruby中更惯用的方法是:

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

我不知道这与速度相比会如何,但问题的一部分可能是因为您不断在字符串上添加一点,并在每次迭代中创建新的更长的字符串对象。连接是在C中完成的,可能会执行得更好。

在ruby中更惯用的方法是:

record = name_hash.map{|k,v| "#{k}|#{v}"}.join("\n")
我不知道这与速度相比会如何,但问题的一部分可能是因为您不断在字符串上添加一点,并在每次迭代中创建新的更长的字符串对象。连接是在C中完成的,可能会执行得更好。

String+速度较慢。这应该会改善它

 record = name_hash.map{|line| line.join("|")}.join("\n")
如果您使用它来输出到某个地方,您不应该创建一个巨大的字符串,而是应该逐行写入输出。

string+很慢。这应该会改善它

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

如果你用它输出到某个地方,你不应该创建一个巨大的字符串,而应该逐行写入输出。

我试过了。每个1M记录哈希都需要5个多小时。我问你是否尝试过你认为是解决方案的方法。哈希迭代本身应该很快。在Ruby 2x中,它是通过一个链接链实现的,用于保持良好的订单属性。迭代过程中正在做什么?100万-100万是一个相当多的项目,因此,即使每个项目需要0.01秒或100/秒,也需要2.7小时。也就是说,问题可能在每个模块内部,而不是每个方法/iter

它本身就是一个例子。也许有更好的方法来解决这个问题?请包含完整的相关代码。正如djconnel在回答中所示,实际的迭代非常快。因此,人们高度怀疑在每个块内部所做的事情是瓶颈。DigitalRoss还建议,如果散列数据来自或利用数据库/模型本身,可能会有一个更好/完全不同的解决方案..一个没有被问到的问题是,您使用的机器上有多少可用RAM?100万条记录的5个小时似乎很长,除非你所在的机器受到内存限制,并且正在交换。我试过了。每100万条记录的哈希需要5个多小时。我想问你是否尝试过你认为是解决方案的方法。哈希迭代本身应该很快。在Ruby 2x中,它是通过一个链接链实现的,用于保持良好的订单属性。迭代过程中正在做什么?100万-100万是一个相当多的项目,因此,即使每个项目需要0.01秒或100/秒,也需要2.7小时。也就是说,问题可能在每个块内部,而不是每个方法/迭代本身。也许有更好的方法来解决这个问题?请包含完整的相关代码。正如djconnel在回答中所示,实际的迭代非常快。因此,人们高度怀疑在每个块内部所做的事情是瓶颈。DigitalRoss还建议,如果散列数据来自或利用数据库/模型本身,可能会有一个更好/完全不同的解决方案..一个没有被问到的问题是,您使用的机器上有多少可用RAM?100万条记录的5个小时似乎很长,除非您所在的计算机受到内存限制并且正在交换。为什么将哈希转换为数组需要大量新对象?此外,在文章中没有明确指出数据来自[关系]数据库..嗯,既然你提到了它,大多数对象将被重用,或者它们将是不可变的内联值。我会更新答案。至于db,他确实用Rails标记了这个问题,而报道的时间似乎太慢了,不可能是其他任何事情。我不是说这不是什么。。傻乎乎的:希望我在主帖子上的评论能提供更多信息。@DigitalRoss我没有使用AR。它只是在处理一个txt文件。那么为什么这个标签是ruby on rails?为什么将哈希转换为数组需要大量新对象?此外,在文章中没有明确指出数据来自[关系]数据库..嗯,既然你提到了它,大多数对象将被重用,或者它们将是不可变的内联值。我会更新答案。至于db,他确实用Rails标记了这个问题,而报道的时间似乎太慢了,不可能是其他任何事情。我不是说这不是什么。。傻乎乎的:希望我在主帖子上的评论能提供更多信息。@DigitalRoss我没有使用AR。它只是在处理一个txt文件。那么为什么这个标签是ruby on rails?所有发布的数字都短于5小时;-+1个用于小基准;虽然它们很小,但它们清楚地表明问题不在于哈希或数组的实现。。这意味着性能瓶颈来自于每个块内部的操作。哇,Ruby 1.8.5?!为什么这么老?Redhat Enterprise Linux版本5。。。我们的代码相当成熟,因为我从事的是支持工作,而不是开发工作,而且我们的升级速度很慢。所有发布的数字都短于5小时;-+1个用于小基准;虽然它们很小,但它们清楚地表明问题不在于哈希或数组的实现。。这意味着性能瓶颈来自于每个块内部的操作。哇,Ruby 1.8.5?!为什么这么老?Redhat Enterprise Linux版本5。。。我们的代码相当成熟,因为我从事的是支持工作,而不是开发工作,而且我们的升级速度很慢。我甚至比我的答案更喜欢这一点!对于任何想知道这和我的答案有什么区别的人,使用一个参数调用map会生成一个数组,[key,value]。我发布的双参数示例只是直接分配键/值。{}比String+快,但我不确定哪个版本的block param更快。我甚至比我的答案更喜欢它!对于任何想知道这和我的答案有什么区别的人,使用一个参数调用map会生成一个数组,[key,value]。我发布的双参数示例只是直接分配键/值。{}比String+快,但我不确定哪个版本的block param更快。您的答案也不错。{…}优于+。我去掉了反斜杠,因为它不会显示在输出中。您的答案也很好。{…}优于+。我去掉了反斜杠,因为它不会显示在输出中。