Как реализовать умное сравнение строк?

Всем привет!

Возникла проблема со сравнением строк.
Задача: Из одной таблицы(она огромна) необходимо сравнить наименование из другой таблицы(тоже огромна, более 20 тысяч строк). Пример наименование1.таблица1 = "Автоматический выключатель KDJF39484", наименование2.таблица2 = "Выключатель автоматический KDJF39484". Или "гайка СБВ-4В ГОСТ.83" и "Гайка СБВ-4ВГОСТ.83". Могут быть разные разделители и присуствие или отсутствие пробелов.
Каким образом сравнить эти строки чтобы выявить что это одно и тоже название?

Буду признательна ссылкам и литературе, вашим советам.
  • Вопрос задан
  • 2558 просмотров
Пригласить эксперта
Ответы на вопрос 8
newross
@newross
Product owner
Можно начать с расстояния Левенштейна.
Ответ написан
Schullz
@Schullz
=^.^=
Без внятного ТЗ результат ХЗ
Ответ написан
streetflush
@streetflush
LCASE( REPLACE ( REPLACE ( REPLACE ( REPLACE ( )))) = LCASE( REPLACE ( REPLACE ( REPLACE ( REPLACE ( ))))
Ответ написан
gobananas
@gobananas
finishhim.ru
На PHP есть, но на C# самим придётся перекладывать:
function GetUniqueStrings($a=array()){

	if(is_array($a)) {
		$out = array();
		foreach($a as $k=>$str){

             	$str = strip_tags(htmlspecialchars(trim($str)));
            	$str = str_replace('  ', ' ', $str);
            	$str = mb_strtolower($str, mb_detect_encoding($str));//не учитываем регистр

			$arr = explode(' ', $str);
	
			$out[$k] = array_reduce($arr, function($sum, $cur){
				$sum += sprintf("%u", crc32($cur));
				return $sum;
			});
		}
		return array_intersect_key($a, array_unique($out));
	}
}
 

$MyArray = [
'автоматический выключатель KDJF39484',
'выключатель автоматический KDJF39484',
'KDJF39484 автоматический выключатель'
];

print_r(GetUniqueStrings($MyArray));

Дефисы можно заменить на пробелы. В случае опечаток типа 4ВГОСТ действительно что-то типа Левенштейна нужно.
Ответ написан
Комментировать
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
Нечёткое сравнение строк (включая опечатки, фонетику и прочее): здесь.
Также, на странице можно тестировать на своих данных.
Ответ написан
Комментировать
al_gon
@al_gon
По большим данным только с поисковым движком.
Всё остальное это сравнения 1:1. Это не промышленные масштабы.

Как реализовать поиск схожести двух строк (названия продуктов)?
Ответ написан
Комментировать
2ord
@2ord
Мне пришёл в голову следующий примитивный алгоритм:
  1. предобработка: переводим в строке заглавные символы в строчные ("Гайка" -> "гайка")
  2. разбиваем строку на токены/слова, разделяемые любым количеством пробелов ("ббб ааа ввв" -> ["ббб", "ааа", "ввв"])
  3. полученный массив слов сортируем лексикографически (["ааа", "ббб", "ввв"])
  4. для последующего сравнения соединим обратно в строку (["ааа", "ббб", "ввв"] -> "ааа ббб ввв")
  5. полученные "нормализованные" строки сравниваем при помощи расстояния Левенштейна

Согласно этому алгоритму из строк "Автоматический выключатель KDJF39484" и "Выключатель автоматический KDJF39484" на выходе получится одинаковая строка "kdjf39484 автоматический выключатель".
Таким образом, расстояние Левенштейна между ними будет равно нулю.

Для строк "гайка СБВ-4В ГОСТ.83", "Гайка СБВ-4ВГОСТ.83" результат хуже ожидаемого из-за того что отсортированы слова "СБВ-4В ГОСТ.83" как "гост.83 сбв-4в". Так получилось из-за того что слитно были написаны каталоговый номер и название стандарта.
Для решения данной проблемы я бы получил из БД репрезентативную выборку всех возможных вариантов наименований, в которых фигурирует "ГОСТ" (без разницы заглавными или строчными) и тогда составил бы правила для отделения от других слов через пробел при помощи регулярных выражений или другими способами. Аналогично в случае с другими названиями стандартов (ISO, ...).

Пример на языке Ruby:
https://gist.github.com/romiras/386e3694a59949f6be...
simple_fuzzy_match(
  ' Автоматический выключатель KDJF39484  ',
  'Выключатель автоматический  KDJF39484'
)
выдаёт разницу 0 для "нормализованных" строк, следовательно, они идентичны.
Ответ написан
igruschkafox
@igruschkafox
Специалист по сопровождению БД MS SQL
Все выше написавшие без образования :)
Сорри ребята :)

Если мы говорим про MS SQL
то в Integration Services имеется Fussy Group и Fussy LookUP

Там сравнение идет по 7 алгоритмам (расстояние между буквами, сколько символов надо заменить, расстояние между символами на клавиатуре и тд)

Вот видео для тех кому лень гуглить
https://www.techdays.ru/videos/1378.html

в оракле тоже такое есть (по моему называется Дата директор)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы