Более эффективный способ запуска find на хэше Ruby? - PullRequest
0 голосов
/ 20 июня 2019

У меня есть массив хэшей, подобный этому:

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 ]

2 голосов
/ 20 июня 2019

Вы можете попробовать группировать по 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.

2 голосов
/ 20 июня 2019

Если вы хотите найти хеш для одного значения "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".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...