Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --drop function meta_form_map.COMPARE_MULTI_STRINGS(text, text, boolean, boolean);
- -- определить степень похожести строк
- CREATE OR REPLACE FUNCTION meta_form_map.COMPARE_MULTI_STRINGS
- (
- S1 text, -- первая строка
- S2 text, -- вторая строка
- IGNORE_CASE boolean = FALSE, -- игнорировать регистр
- RELATIVE_LENGTH boolean = FALSE -- если задано, возвращает относительную разницу строк
- )
- RETURNS real LANGUAGE plpgsql
- AS $FUNCTION$
- declare
- valueOfReplace real = 1.0; -- цена замены символа строки
- valueOfDelete real = 1.0; -- цена удаления символа строки
- valueOfInsert real = 1.0; -- цена вставки символа строки
- W1 text[]; -- первая последовательность строк
- W2 text[]; -- вторая последовательность строк
- L1 integer; -- длина первой последовательности строк
- L2 integer; -- длина второй последовательности строк
- C1 text;
- C2 text;
- DIFFERENCE real;
- D real[][];
- BEGIN
- IF IGNORE_CASE THEN
- -- игнорируем регистр
- S1 := upper(S1);
- S2 := upper(S2);
- END IF;
- -- разбиваем строки на токены
- select array_agg(WORD) into W1
- from (select regexp_split_to_table(trim(S1), E'\\s+') WORD) e
- where length(WORD) > 2;
- -- разбиваем строки на токены
- select array_agg(WORD) into W2
- from (select regexp_split_to_table(trim(S2), E'\\s+') WORD) e
- where length(WORD) > 2;
- L1 := array_length(W1, 1);
- L2 := array_length(W2, 1);
- -- создаем массив
- D := array_fill(0, array[L1 + 1, L2 + 1]);
- -- начальная инициализация
- FOR i IN 1..L1 + 1 LOOP
- D[i][1] := (i - 1)::real;
- END LOOP;
- FOR j IN 1..L2 + 1 LOOP
- D[1][j] := (j - 1)::real;
- END LOOP;
- -- главный цикл
- FOR i IN 2..L1 + 1 LOOP
- FOR j IN 2..L2 + 1 LOOP
- -- если символы совпадают то ничего делать не надо
- C1 := W1[i - 1];
- C2 := W2[j - 1];
- DIFFERENCE := meta_form_map.COMPARE_STRINGS(C1, C2, RELATIVE_LENGTH := TRUE);
- --DIFFERENCE := meta_form_map.COMPARE_STRINGS(C1, C2);
- D[i][j] := least
- (
- D[i - 1][j] + valueOfDelete,
- D[i][j - 1] + valueOfInsert,
- D[i - 1][j - 1] + valueOfReplace * DIFFERENCE
- );
- END LOOP;
- END LOOP;
- -- отладочный вывод
- --RAISE NOTICE 'D: %', D;
- IF RELATIVE_LENGTH THEN
- RETURN D[L1 + 1][L2 + 1] / greatest(L1, L2)::real;
- --RETURN D[L1 + 1][L2 + 1] / greatest(length(S1), length(S1))::real;
- ELSE
- RETURN D[L1 + 1][L2 + 1];
- END IF;
- END;
- $FUNCTION$
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement