在Ruby哈希上运行find的更有效方法?

时间:2019-06-20 00:08:28

标签: ruby hash

我有一系列类似于以下的哈希值:

rules = [{
  "id" => "artist_name",
  "type" => "string",
  "field" => "artist_name",
  "input" => "text",
  "value" => "Underoath",
  "operator" => "contains"
},
{
  "id" => "bpm",
  "type" => "integer",
  "field" => "bpm",
  "input" => "number",
  "value" => 100,
  "operator" => "greater"
}]

我正在对此运行find以选择所需的哈希值:

rules.find {|h| h['id'] == 'artist_name'}

但是我需要针对许多不同的“规则”执行此操作,这感觉有些冗长。

也许这实际上是获取特定“规则”的最有效方法,但我的直觉是有一个Ruby方法可以更好地做到这一点。

如果我只需要编写自己的方法,那很好,但是想看看是否有一种我不熟悉的方法。

那么,有没有办法以更紧凑/更有效的方式来编写rules.find {|h| h['id'] == 'artist_name'}

2 个答案:

答案 0 :(得分:2)

如果要查找单个值"id"的哈希,则显然必须执行线性搜索。另一方面,如果您希望对"id"的不同值进行多次查找,那么明智的做法是使用适当的键创建哈希。

rules = [{
  "id"       => "artist_name",
  "type"     => "string",
  "field"    => "artist_name",
  "input"    => "text",
  "value"    => "Underoath",
  "operator" => "contains"
},
{
  "id"       => "bpm",
  "type"     => "integer",
  "field"    => "bpm",
  "input"    => "number",
  "value"    => 100,
  "operator" => "greater"
}]

h = rules.each_with_index.with_object({}) { |(g,i),h| h[g["id"]] = i }
  #=> {"artist_name"=>0, "bpm"=>1} 

h的值是rules的元素(哈希)的索引。因此,"id"=>"bpm"的哈希值是

rules[h["bpm"]
  #=> {"id"=>"bpm", "type"=>"integer", "field"=>"bpm", "input"=>"number",
  #    "value"=>100, "operator"=>"greater"}

我本可以将h的元素本身的值rules进行设置,但这将需要更多的存储空间而又不会显着缩短查找时间。

对于这个问题,目前尚不清楚"id"的值对于rules的两个或更多元素是否可以相同。如果是这种情况,h的键数将少于rules的元素数,但是问题的措辞表明可以选择具有相同值"id"的键中的任何哈希值。 / p>

答案 1 :(得分:2)

您可以尝试按id进行分组,并使其成为要查找的哈希键。例如

grouped_rules = rules.group_by { |r| r["id"] }
# => {"artist_name"=>[{"id"=>"artist_name", "type"=>"string", "field"=>"artist_name", "input"=>"text", "value"=>"Underoath", "operator"=>"contains"}], "bpm"=>[{"id"=>"bpm", "type"=>"integer", "field"=>"bpm", "input"=>"number", "value"=>100, "operator"=>"greater"}]}

grouped_rules["artist_name"]
# => [{"id"=>"artist_name", "type"=>"string", "field"=>"artist_name", "input"=>"text", "value"=>"Underoath", "operator"=>"contains"}]

这绝对是更紧凑和可读的,但是它是否“有效”取决于您打算如何评估/评估它。这并不能提高内存效率,但是如果您以前经常使用find,则应该更快。