Поиск данных - одна из самых частых операций в программировании. В Ruby для массивов и хэшей существует множество методов поиска, каждый из которых имеет свои особенности и оптимальные сценарии использования.
Базовые методы, проверяющие элементы последовательно:
# find/detect - возвращает первый элемент, удовлетворяющий условию
[1, 2, 3, 4].find { |x| x.even? } #=> 2
# select/filter - возвращает все подходящие элементы
[1, 2, 3, 4].select { |x| x.even? } #=> [2, 4]
# any?/all?/none? - проверка условий
[1, 2, 3].any? { |x| x > 2 } #=> true
Для отсортированных массивов (O(log n) сложность):
# bsearch/bsearch_index
sorted = [10, 20, 30, 40, 50]
sorted.bsearch { |x| x >= 25 } #=> 30
# index - поиск по значению
['a', 'b', 'c'].index('b') #=> 1
# find_index - аналог index
[1, 2, 3].find_index { |x| x > 1 } #=> 1
# rindex - поиск с конца
[1, 2, 3, 2].rindex(2) #=> 3
# include? - проверка наличия
[1, 2, 3].include?(2) #=> true
hash = { a: 1, b: 2, c: 3 }
# Доступ по ключу
hash[:b] #=> 2
# fetch - с обработкой отсутствия ключа
hash.fetch(:d, 'default') #=> 'default'
# key?/has_key? - проверка наличия ключа
hash.key?(:a) #=> true
# value?/has_value?
hash.value?(2) #=> true
# key - поиск ключа по значению
hash.key(2) #=> :b
# select/filter
hash.select { |k, v| v > 1 } #=> { b: 2, c: 3 }
# reject
hash.reject { |k, v| v < 2 } #=> { b: 2, c: 3 }
Метод | Массив | Хэш | Сложность |
---|---|---|---|
Линейный поиск | Да | Нет | O(n) |
Бинарный поиск | Да* | Нет | O(log n) |
По ключу | Нет | Да | O(1) |
По значению | Да | Да | O(n) |
*Только для отсортированных массивов
Для частых поисков в массиве:
array.to_h { |x| [x, true] }
require 'set'; set = array.to_set
Для хэшей:
Резюмируем: выбор метода поиска зависит от структуры данных и требований к производительности. Хэши оптимальны для поиска по ключу (O(1)), массивы требуют более тщательного выбора алгоритма (от O(1) для index до O(n) для линейного поиска). Для сложных условий используйте select
/find
с блоками.