Postgres array_replace()函数替换子数组

时间:2018-06-13 14:52:52

标签: arrays postgresql replace

当您需要替换数组中的单个元素时,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 :(得分:1)

听起来你想要的是数组上的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'))))

(我确信有一种方法可以通过位置索引,创建函数等来实现这一点,但这是我的快速解决方案。)

答案 1 :(得分:1)

该功能可能如下所示:

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)