Advertisement
Doomer3D

COMPARE_MULTI_STRINGS

Mar 14th, 2017
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --drop function meta_form_map.COMPARE_MULTI_STRINGS(text, text, boolean, boolean);
  2.  
  3. -- определить степень похожести строк
  4. CREATE OR REPLACE FUNCTION meta_form_map.COMPARE_MULTI_STRINGS
  5.   (
  6.     S1 text,                                    -- первая строка
  7.     S2 text,                                    -- вторая строка
  8.     IGNORE_CASE boolean = FALSE,                -- игнорировать регистр
  9.     RELATIVE_LENGTH boolean = FALSE             -- если задано, возвращает относительную разницу строк
  10.   )
  11.   RETURNS real LANGUAGE plpgsql
  12. AS $FUNCTION$
  13. declare
  14.     valueOfReplace real = 1.0;                  -- цена замены символа строки
  15.     valueOfDelete  real = 1.0;                  -- цена удаления символа строки
  16.     valueOfInsert  real = 1.0;                  -- цена вставки символа строки
  17.     W1 text[];                                  -- первая последовательность строк
  18.     W2 text[];                                  -- вторая последовательность строк
  19.     L1 integer;                                 -- длина первой последовательности строк
  20.     L2 integer;                                 -- длина второй последовательности строк
  21.     C1 text;
  22.     C2 text;
  23.     DIFFERENCE real;
  24.     D real[][];
  25. BEGIN
  26.     IF IGNORE_CASE THEN
  27.       -- игнорируем регистр
  28.       S1 := upper(S1);
  29.       S2 := upper(S2);
  30.     END IF;
  31.    
  32.     -- разбиваем строки на токены
  33.     select array_agg(WORD) into W1
  34.       from (select regexp_split_to_table(trim(S1), E'\\s+') WORD) e
  35.      where length(WORD) > 2;
  36.            
  37.     -- разбиваем строки на токены
  38.     select array_agg(WORD) into W2
  39.       from (select regexp_split_to_table(trim(S2), E'\\s+') WORD) e
  40.      where length(WORD) > 2;
  41.    
  42.     L1 := array_length(W1, 1);
  43.     L2 := array_length(W2, 1);
  44.    
  45.     -- создаем массив
  46.     D := array_fill(0, array[L1 + 1, L2 + 1]);
  47.    
  48.     -- начальная инициализация
  49.     FOR i IN 1..L1 + 1 LOOP
  50.        D[i][1] := (i - 1)::real;
  51.     END LOOP;
  52.     FOR j IN 1..L2 + 1 LOOP
  53.        D[1][j] := (j - 1)::real;
  54.     END LOOP;
  55.    
  56.     -- главный цикл
  57.     FOR i IN 2..L1 + 1 LOOP
  58.         FOR j IN 2..L2 + 1 LOOP
  59.             -- если символы совпадают то ничего делать не надо
  60.             C1 := W1[i - 1];
  61.             C2 := W2[j - 1];
  62.             DIFFERENCE := meta_form_map.COMPARE_STRINGS(C1, C2, RELATIVE_LENGTH := TRUE);
  63.             --DIFFERENCE := meta_form_map.COMPARE_STRINGS(C1, C2);
  64.            
  65.             D[i][j] := least
  66.             (
  67.                 D[i - 1][j] + valueOfDelete,
  68.                 D[i][j - 1] + valueOfInsert,
  69.                 D[i - 1][j - 1] + valueOfReplace * DIFFERENCE
  70.             );
  71.         END LOOP;
  72.     END LOOP;
  73.    
  74.     -- отладочный вывод
  75.     --RAISE NOTICE 'D: %', D;
  76.    
  77.     IF RELATIVE_LENGTH THEN
  78.         RETURN D[L1 + 1][L2 + 1] / greatest(L1, L2)::real;
  79.         --RETURN D[L1 + 1][L2 + 1] / greatest(length(S1), length(S1))::real;
  80.     ELSE
  81.         RETURN D[L1 + 1][L2 + 1];
  82.     END IF;
  83. END;
  84. $FUNCTION$
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement