当您需要替换数组中的单个元素时,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]);
如何创建这样的功能?
答案 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)