简体   繁体   English

如何从散列哈希中有效地提取具有某个键名的所有值?

[英]How do I efficiently extract all values with a certain key name from a hash of hashes?

I have this data: 我有这些数据:

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"}
]}

And want to generate an array like: 并希望生成如下数组:

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

Currently I'm using: 目前我正在使用:

members['data'].collect { |h| h['email'] }
  1. Is there a more efficient way to achieve it in regards to performance? 在性能方面有没有更有效的方法来实现它?
  2. Is there an even shorter way to achieve it? 有没有更短的方法来实现它?

I have Rails available. 我有Rails可用。

Additionally to the other answers, I'll add the if you're able to construct the Hash using symbols as keys you can have a performance gain when collecting the values, for instance: 除了其他答案之外,我将添加如果您能够使用symbols作为keys来构造Hash ,您可以在收集值时获得performance增益,例如:

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

Results: 结果:

        user     system      total        real
Without symbol  2.260000   0.000000   2.260000 (  2.254277)
With symbol  0.880000   0.000000   0.880000 (  0.878603)

Other than optimising the h['email'] part into native extensions, I cannot see how you could make the above example more efficient. 除了将h['email']部分优化为原生扩展之外,我无法看到如何使上述示例更有效。 The efficiency gain of doing so would be tiny for the example size of data set, and much less than optimising I/O of fetching/parsing this data in the first place I'd suspect. 这样做的效率增益对于数据集的示例大小来说是微不足道的,并且比我首先想到的优化获取/解析这些数据的I / O要小得多。

Depending on your data source, having the hash keys as labels, and not strings, is a common Ruby idiom, and also more efficient in terms of memory use. 根据您的数据源,将散列键作为标签而不是字符串,是一种常见的Ruby习惯用法,并且在内存使用方面也更有效。 This is potentially a larger gain in efficiency, and might be worth it provided you don't have to put a large amount of effort in to convert the data (eg you can somehow change the nature of the given data structure from your data source, without needing to convert the hash just to query it once!) 这可能是效率的更大提升,并且可能是值得的,只要您不必花费大量精力来转换数据(例如,您可以以某种方式改变数据源中给定数据结构的性质,无需转换哈希只是查询一次!)

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"]}

gives you ["foo@example.org", "bar@example.org", "exx@example.org"] 给你[“foo@example.org”,“bar @ example.org”,“exx@example.org”]

Difference between map and collect in Ruby? Ruby中的map和collect之间的区别?

-- -

Maybe Structs would improve performance 也许Structs可以提高性能

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 http://blog.rubybestpractices.com/posts/rklemme/017-Struct.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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