Функция Postgres array_replace () для замены подмассива - PullRequest
0 голосов
/ 13 июня 2018

Функция postgres array_replace(anyarray, anyelement, anyelement) полезна, когда вам нужно заменить один элемент в массиве.

Но мне нужно заменить последовательность элементов в массиве другой последовательностью.Я хотел бы иметь такую ​​функцию: array_replace(anyarray, anyarray, anyarray)

Например.Если у меня есть этот массив: [A, B, C, D, E, F]

Я бы хотел изменить его на [A, 1, 2, 3, D, E, F]

Вызвав такую ​​функцию: array_replace([A, B, C, D, E, F], [B, C], [1, 2, 3]);

Элементыподлежащие замене все должны быть в точном порядке, в котором они передаются функции, одна за другой.Таким образом, следующий вызов не изменяет исходный массив, поскольку B и C не находятся рядом с элементами исходного массива:

array_replace([A, B, X, C, D, E, F], [B, C], [1, 2, 3]);

Как мне создать такую ​​функцию?

Ответы [ 2 ]

0 голосов
/ 15 июня 2018

Функция может выглядеть следующим образом:

create or replace function array_replace_array(anyarray, anyarray, anyarray)
returns anyarray language plpgsql as $$
declare
    l1 int = array_length($1, 1);
    l2 int = array_length($2, 1);
    i int;
begin
    for i in 1 .. l1- l2+ 1 loop
        if $1[i : i+ l2- 1] = $2 then
            return $1[1 : i- 1] || $3 || $1[i+ l2 : l1];
        end if;
    end loop;
    return $1;
end $$;

Примеры:

select 
    array_replace_array('{A,B,C,D,E}'::text[], '{B,C}', '{X,Y,Z}') as "AXYZDE",
    array_replace_array('{A,B,C,D,E}'::text[], '{B,B}', '{X,Y,Z}') as "ABCDE",
    array_replace_array('{A,B,C,D,E}'::text[], '{A,B,C,D,E}', '{X,Y,Z}') as "XYZ",
    array_replace_array('{1,2,3,4}'::int[], '{2,3}', '{3,2}') as "1324";

    AXYZDE     |    ABCDE    |   XYZ   |   1324    
---------------+-------------+---------+-----------
 {A,X,Y,Z,D,E} | {A,B,C,D,E} | {X,Y,Z} | {1,3,2,4}
(1 row)
0 голосов
/ 13 июня 2018

Звучит так, как будто вы хотите получить regexp_replace над массивом.Postgres позволяет преобразовывать массивы в строки (и наоборот).Однако хитрость заключается в том, чтобы обрабатывать каждый элемент массива как слово и сопоставлять его с эквивалентными границами слова.

Следующий код возвращает {A,1,2,3,D,E,F}

Select array(
    select regexp_replace(
          (select array_to_string(array['A','B','C','D','E','F'],', ')),
          (select ' ' || array_to_string(array['B','C']),', ')),
          (select array_to_string(array[1,2,3],',')),
          'g'))))

(я уверен, чтоспособ сделать это с помощью позиционной индексации, создания функции и т. д., но это мое быстрое решение).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...