Учитывая строку поиска и строку результата (которая гарантированно содержит все буквы строки поиска, без учета регистра, по порядку), как я могу наиболее эффективно получить массив диапазонов, представляющих индексы в строке результата, соответствующие буквам в строке поиска?
Желаемый результат:
substrings( "word", "Microsoft Office Word 2007" )
#=> [ 17..20 ]
substrings( "word", "Network Setup Wizard" )
#=> [ 3..5, 19..19 ]
#=> [ 3..4, 18..19 ] # Alternative, acceptable, less-desirable output
substrings( "word", "Watch Network Daemon" )
#=> [ 0..0, 10..11, 14..14 ]
Это для окна поиска с автозаполнением. Вот скриншот из инструмента , похожего на Quicksilver , который подчеркивает буквы, как я хочу. Обратите внимание, что - в отличие от моего идеального результата выше - этот снимок экрана не предпочитает более длинные одиночные совпадения.
Тестирование текущих рабочих результатов показывает, что ответ @ tokland на основе регулярных выражений в основном такой же быстрый, как и на основе StringScanner предлагаемые мной решения с меньшим количеством кода:
user system total real
phrogz1 0.889000 0.062000 0.951000 ( 0.944000)
phrogz2 0.920000 0.047000 0.967000 ( 0.977000)
tokland 1.030000 0.000000 1.030000 ( 1.035000)
Вот тест производительности:
a=["Microsoft Office Word 2007","Network Setup Wizard","Watch Network Daemon"]
b=["FooBar","Foo Bar","For the Love of Big Cars"]
test = { a=>%w[ w wo wor word ], b=>%w[ f fo foo foobar fb fbr ] }
require 'benchmark'
Benchmark.bmbm do |x|
%w[ phrogz1 phrogz2 tokland ].each{ |method|
x.report(method){ test.each{ |words,terms|
words.each{ |master| terms.each{ |term|
2000.times{ send(method,term,master) }
} }
} }
}
end