Ответ 1
Резюме
Если вы собираетесь тестировать только одно слово против массива или если содержимое вашего массива изменяется часто, самым быстрым ответом является Aaron's:
array.any?{ |s| s.casecmp(mystr)==0 }
Если вы собираетесь тестировать много слов против статического массива, гораздо лучше использовать вариант ответа farnoy: создайте копию вашего массива со всеми строчными версиями ваших слов и используйте include?
. (Предполагается, что вы можете освободить память для создания мутированной копии вашего массива.)
# Do this once, or each time the array changes
downcased = array.map(&:downcase)
# Test lowercase words against that array
downcased.include?( mystr.downcase )
Еще лучше, создайте Set
из вашего массива.
# Do this once, or each time the array changes
downcased = Set.new array.map(&:downcase)
# Test lowercase words against that array
downcased.include?( mystr.downcase )
Мой первоначальный ответ ниже - очень плохой исполнитель и обычно не подходит.
Бенчмарки
Ниже приведены ориентиры для поиска 1000 слов со случайным корпусом в массиве чуть более 100 000 слов, где 500 слов будут найдены, а 500 не будут.
- Текст 'regex' - это мой ответ здесь, используя
any?
. - Тест "casecmp" - это ответ Arron, используя
any?
из моего комментария. - Тест "downarray" - это ответ farnoy, воссоздающий новый уменьшенный массив для каждого из 1000 тестов.
- Тест "downonce" - это ответ farnoy, но только предварительный создание массива поиска.
- Тест 'set_once' создает
Set
из массива строк с нижним уровнем, один раз перед тестированием.
user system total real
regex 18.710000 0.020000 18.730000 ( 18.725266)
casecmp 5.160000 0.000000 5.160000 ( 5.155496)
downarray 16.760000 0.030000 16.790000 ( 16.809063)
downonce 0.650000 0.000000 0.650000 ( 0.643165)
set_once 0.040000 0.000000 0.040000 ( 0.038955)
Если вы можете создать одиночную копию вашего массива один раз, чтобы выполнить множество запросов, farnoy отвечает наилучшим образом (предполагая, что вы должны использовать массив). Если вы можете создать Set
, сделайте это.
Если вам нравится, проверить код бенчмаркинга.
Оригинальный ответ
I (первоначально сказал, что я) лично создавал не зависящее от регистра регулярное выражение (для строкового литерала) и использовал бы это:
re = /\A#{Regexp.escape(str)}\z/i # Match exactly this string, no substrings
all = array.grep(re) # Find all matching strings…
any = array.any?{ |s| s =~ re } # …or see if any matching string is present
Использование any?
может быть немного быстрее, чем grep
, поскольку он может выйти из цикла, как только он найдет одно совпадение.