Вот над чем можно подумать:
Итерация по массиву в поисках чего-то выполняется медленно, даже если это отсортированный массив. В компьютерных языках есть различные структуры, которые мы можем использовать для повышения скорости поиска, и Ruby Ha sh обычно является хорошей отправной точкой. Если массив похож на чтение из последовательного файла, Ha sh похож на чтение из файла с произвольным доступом, мы можем сразу перейти к нужной нам записи.
Начиная с вашего test
массива- of-hashes:
test = [
{'type'=>1337, 'age'=>12, 'name'=>'Eric Johnson'},
{'type'=>1338, 'age'=>18, 'name'=>'John Doe'},
{'type'=>1339, 'age'=>22, 'name'=>'Carl Adley'},
{'type'=>1340, 'age'=>25, 'name'=>'Anna Brent'},
{'type'=>1341, 'age'=>13, 'name'=>'Eric Johnson'},
]
Обратите внимание, что я добавил дополнительную запись «Eri c Johnson». Я вернусь к этому позже.
Я бы создал ha sh, который сопоставил бы массив хэшей с обычным ha sh, где ключ каждой пары является уникальным значением. Пара ключ / значение 'type'
, похоже, подходит для этой потребности:
test_by_types = test.map { |h| [
h['type'], h]
}.to_h
# => {1337=>{"type"=>1337, "age"=>12, "name"=>"Eric Johnson"},
# 1338=>{"type"=>1338, "age"=>18, "name"=>"John Doe"},
# 1339=>{"type"=>1339, "age"=>22, "name"=>"Carl Adley"},
# 1340=>{"type"=>1340, "age"=>25, "name"=>"Anna Brent"},
# 1341=>{"type"=>1341, "age"=>13, "name"=>"Eric Johnson"}}
Теперь test_by_types
- это ha sh с использованием значения type
для указания на исходный ha sh.
Если я создам аналогичный ha sh на основе имен, где каждое имя, уникальное или нет, указывает на значения type
, я могу выполнять быстрый поиск:
test_by_names = test.each_with_object(
Hash.new { |h, k| h[k] = [] }
) { |e, h|
h[e['name']] << e['type']
}.to_h
# => {"Eric Johnson"=>[1337, 1341],
# "John Doe"=>[1338],
# "Carl Adley"=>[1339],
# "Anna Brent"=>[1340]}
Обратите внимание, что «Eri c Johnson» указывает на две записи.
Теперь, вот как мы ищем вещи:
get_hash_by_name = ['John Doe', 'Anna Brent']
test_by_names.values_at(*get_hash_by_name).flatten
# => [1338, 1340]
За один быстрый поиск Ruby вернул совпадение types
путем поиска имен.
Мы можем взять этот вывод и получить исходные хэши:
test_by_types.values_at(*test_by_names.values_at(*get_hash_by_name).flatten)
# => [{"type"=>1338, "age"=>18, "name"=>"John Doe"},
# {"type"=>1340, "age"=>25, "name"=>"Anna Brent"}]
Поскольку это работает против хешей, это быстро. Хеши могут быть БОЛЬШИМИ, и они все равно будут работать очень быстро.
Вернуться к «Эри c Джонсон» ...
При работе с именами людей могут возникнуть конфликты имен, поэтому test_by_names
допускает несколько значений type
, поэтому с помощью одного поиска можно получить все совпадающие записи:
test_by_names.values_at('Eric Johnson').flatten
# => [1337, 1341]
test_by_types.values_at(*test_by_names.values_at('Eric Johnson').flatten)
# => [{"type"=>1337, "age"=>12, "name"=>"Eric Johnson"},
# {"type"=>1341, "age"=>13, "name"=>"Eric Johnson"}]
Это будет много, если вы новинка Ruby, но документация Ruby охватывает все это, так что покопайтесь в документации классов Ha sh, Array и Enumerable .
Кроме того, *
, также известный как «splat», разбивает элементы массива из включающего массива на отдельные параметры, подходящие для передачи в метод. Я не могу вспомнить, где это задокументировано.
Если вы знакомы с дизайном базы данных, это будет выглядеть очень знакомо, потому что это похоже на то, как мы выполняем поиск в базе данных.
Суть всего Дело в том, что действительно важно подумать о том, как вы собираетесь хранить свои данные, когда вы впервые вставляете их в свою программу. Сделайте это неправильно, и вы перепрыгнете через серьезные препятствия, пытаясь сделать с ним полезные вещи. Сделайте это правильно, и код и данные будут передаваться очень легко, и вы сможете легко массировать / извлекать / комбинировать данные.
Другими словами, массивы - это контейнеры, полезные для хранения вещей, к которым вы хотите получить доступ последовательно, например заданий, которые вы хотите распечатать, сайтов, к которым вам нужно получить доступ по порядку, файлов, которые вы хотите удалить, в определенном порядке c , но они ужасны, когда вы хотите искать и работать с записью случайным образом.
Важно знать, какой контейнер подходит, и для этой конкретной задачи оказывается, что массив хэшей не подходит, так как нет быстрого способа доступа к определенным c единицам.
И поэтому я сделал свой комментарий выше, спрашивая, что вы пытались сделать sh в первую очередь. См. « В чем проблема XY? » и « XyProblem » для получения дополнительной информации по этому конкретному вопросу.