2012-03-22 3 views
10

Id любят сравнивать две строки в Ruby, и найти их сходстворубин сравнить две строки сходства в процентах

Я имел взгляд на Levenshtein драгоценный камень, но, кажется, это был последний раз обновлялся в 2008 году, и я не могу найти документация, как его использовать. С некоторыми блоги предполагая его сломанной

Я попробовал text камень с Левенштейн, но это дает целое (меньше, тем лучше)

Очевидно, что если две строки переменной длины я бегу в проблемы с Левенштейна алгоритма (Say сравнивая два имени, где одно имеет среднее имя, а другое - не).

Что бы вы посоветовали, чтобы получить процентное сравнение?

Edit: Im ищет что-то похожее на РНР similar text

+0

Возможно дубликат http://stackoverflow.com/questions/4761793/how-to-do-advanced-string-comparison-in-ruby –

+0

Это порождает список различий, им ищет% сходства – Akshat

+0

Если строки имеют разную длину, которую нужно взять за основу для вычисления процента? –

ответ

14

Я думаю, что ваш вопрос может сделать с некоторыми уточнениями, но вот что-то быстро и грязно (расчет в процентах от длинной строки в соответствии с вашим осветлением выше) :

def string_difference_percent(a, b) 
    longer = [a.size, b.size].max 
    same = a.each_char.zip(b.each_char).select { |a,b| a == b }.size 
    (longer - same)/a.size.to_f 
end 

Я до сих пор не знаю, как много смысла в этом разница процентов вы ищете делает, но это должно вам начать работу по крайней мере.

Это немного похоже на расстояние Левенштейна, в котором он сравнивает символ строк по характеру. Так что, если два имени отличаются только от среднего имени, они на самом деле будут совсем другими.

+0

Может кто-нибудь объяснить «тот же» бит? Таким образом, он перебирает каждый символ, в то время как zip создает массив для каждого символа в строке A с - то, что я ожидаю, будет - каждый символ в строке B. Как второй each_char знает, какой индекс объединяется в массив? –

+0

Кроме того, этот расчет не работает, когда в начале изменяется один символ. –

+1

Остерегайтесь ** a ** в Select, потому что он очищает переменную, переданную параметром. Лучше использовать другие буквы. 'same = a.each_char.zip (b.each_char) .select {| c, d | c == d} .size' – sesperanto

12

В настоящее время существует рубиновый камень для аналогичного текста. https://rubygems.org/gems/similar_text Он предоставляет метод similar, который сравнивает две строки и возвращает число, представляющее процентное сходство между двумя строками.

+2

Подобный_text gem зависает на больших строках, пробовал 143kb html-страницу –

9

Я могу порекомендовать драгоценный камень fuzzy-string-match.

Вы можете использовать его, как это (взято из the docs):

require "fuzzystringmatch" 
jarow = FuzzyStringMatch::JaroWinkler.create(:native) 
p jarow.getDistance("jones", "johnson") 

Это вернет счет ~0.832, который рассказывает, как хороший матч этих строк.

Смежные вопросы