3

我有这个数据:

members = {"total"=>3, "data"=>[
  {"email"=>"foo@example.org", "timestamp"=>"2013-03-16 01:11:01"},
  {"email"=>"bar@example.org", "timestamp"=>"2013-03-16 02:07:30"},
  {"email"=>"exx@example.org", "timestamp"=>"2013-03-16 03:06:24"}
]}

并想生成一个数组,如:

["foo@example.org", "bar@example.org", "exx@example.org"]

目前我正在使用:

members['data'].collect { |h| h['email'] }
  1. 在性能方面是否有更有效的方法来实现它?
  2. 有没有更短的方法来实现它?

我有可用的 Rails。

4

3 回答 3

4

除了其他答案之外,我将添加如果您能够构建Hashusing symbols,因为keysperformance在收集值时可以获得收益,例如:

require 'benchmark'

members_without_sym = {"total"=>3, "data"=>[
  {"email"=>"foo@example.org", "timestamp"=>"2013-03-16 01:11:01"},
  {"email"=>"bar@example.org", "timestamp"=>"2013-03-16 02:07:30"},
  {"email"=>"exx@example.org", "timestamp"=>"2013-03-16 03:06:24"}
]}

members_with_sym = {:total=>3, :data=>[
  {:email=> "foo@example.org", :timestamp => "2013-03-16 01:11:01"},
  {:email=> "bar@example.org", :timestamp => "2013-03-16 02:07:30"},
  {:email=> "exx@example.org", :timestamp=> "2013-03-16 03:06:24"}
]}

Benchmark.bm(1) do |algo|
  algo.report("Without symbol"){
    2_000_000.times do 
       members_without_sym['data'].collect { |h| h['email'] }
    end   
  }
  algo.report("With symbol"){
    2_000_000.times do 
      members_with_sym[:data].collect { |h| h[:email] }      
    end
  }
end

结果:

        user     system      total        real
Without symbol  2.260000   0.000000   2.260000 (  2.254277)
With symbol  0.880000   0.000000   0.880000 (  0.878603)
于 2013-03-16T14:15:00.783 回答
3

除了将h['email']部分优化为原生扩展之外,我看不出如何使上述示例更高效。这样做的效率增益对于数据集的示例大小来说是很小的,并且比我怀疑的首先优化获取/解析这些数据的 I/O 少得多。

根据您的数据源,将哈希键作为标签而不是字符串是一种常见的 Ruby 习惯用法,并且在内存使用方面也更有效。这可能会提高效率,如果您不必花费大量精力来转换数据,这可能是值得的(例如,您可以以某种方式从数据源更改给定数据结构的性质,无需转换哈希即可查询一次!)

于 2013-03-16T13:57:20.250 回答
2
members = {"total"=>3, "data"=>[
  {"email"=>"foo@example.org", "timestamp"=>"2013-03-16 01:11:01"},
  {"email"=>"bar@example.org", "timestamp"=>"2013-03-16 02:07:30"},
  {"email"=>"exx@example.org", "timestamp"=>"2013-03-16 03:06:24"}
]}

temp = members["data"].map{|x|x["email"]}

给你 ["foo@example.org", "bar@example.org", "exx@example.org"]

Ruby中地图和收集之间的区别?

--

也许结构会提高性能

Record = Struct.new(:email, :timestamp)
members = {"total"=>3, "data"=>[
  Record.new("foo@example.org","2013-03-16 01:11:01"),
  Record.new("bar@example.org","2013-03-16 02:07:30"),
  Record.new("exx@example.org","2013-03-16 03:06:24")
]}

temp = members["data"].map(&:email)

http://blog.rubybestpractices.com/posts/rklemme/017-Struct.html

于 2013-03-16T14:02:11.623 回答