Arrays 在文本数组上应用'trim()'和'regexp_replace()'
我正在尝试将PostgreSQL文本数组转换为一个数组,其中每个值都被一个值替换,其中每个空格的每一侧都由一个字符包围。换句话说,我试图对文本数组中的每个值应用Arrays 在文本数组上应用'trim()'和'regexp_replace()',arrays,postgresql,plpgsql,trim,Arrays,Postgresql,Plpgsql,Trim,我正在尝试将PostgreSQL文本数组转换为一个数组,其中每个值都被一个值替换,其中每个空格的每一侧都由一个字符包围。换句话说,我试图对文本数组中的每个值应用trim()和regexp\u replace()。这一切都是在数据库函数中完成的(除其他外) CREATE OR REPLACE FUNCTION manipulate_array(multiplevalues text[]) RETURNS text[] AS $BODY$ DECLARE
trim()
和regexp\u replace()
。这一切都是在数据库函数中完成的(除其他外)
CREATE OR REPLACE FUNCTION manipulate_array(multiplevalues text[])
RETURNS text[] AS
$BODY$
DECLARE
singlevalue text;
BEGIN
FOREACH singlevalue IN ARRAY multiplevalues LOOP
SELECT trim(regexp_replace(singlevalue, '\s+', ' ', 'g')) INTO singlevalue;
END LOOP;
RETURN multiplevalues;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION manipulate_array(multiplevalues text[]) OWNER TO username;
不幸的是,当我使用multiplevalues='{“red”、“blue”、“yellow”}'
作为参数之一调用函数时,返回的值是完全相同的文本数组。如何获取'{“红色”、“蓝色”、“黄色”}'
作为返回值
我已经盯着
trim()
、regexp\u replace()
和FOREACH
循环的定义看了一段时间了,我可能只需要其他人检查一下。您的代码永远不会更改多值数组。它只是更改每个元素,然后丢弃新值
您需要一个变量,用于将结果聚合为:
CREATE OR REPLACE FUNCTION manipulate_array(multiplevalues text[])
RETURNS text[] AS
$BODY$
DECLARE
singlevalue text;
l_result text[] := '{}'::text[]; -- initialize with an empty array
BEGIN
FOREACH singlevalue IN ARRAY multiplevalues LOOP
SELECT trim(regexp_replace(singlevalue, '\s+', ' ', 'g')) INTO singlevalue;
l_result := l_result || singlevalue; -- append to the result
END LOOP;
RETURN l_result; -- return the new array, not the old one
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
但是,使用unnest和array_agg以及简单的SQL函数(而不是PL/pgSQL)可以简化这一点
您需要首先取消数组的测试,将值和聚合修剪回数组中
我不确定我是否理解您试图执行的操作,但这将修剪数组中的所有值并返回一个新值:
create function trim_all(p_values text[])
returns text[]
as
$$
select array_agg(trim(regexp_replace(t.v, '\s+', ' ', 'g')) order by t.nr)
from unnest(p_values) with ordinality as t(v, nr);
$$
language sql;
还有一些改进:
CREATE FUNCTION trim_all1(text[])
RETURNS text[] AS
$func$
SELECT ARRAY (
SELECT regexp_replace(trim(elem), '\s+', ' ', 'g')
FROM unnest($1) elem
)
$func$ LANGUAGE sql IMMUTABLE;
- 在昂贵的
regexp\u replace()
之前应用便宜的trim()
通常会更快
- simple比
数组\u agg()
更快地聚合单个数组
- 使函数
不可变
(因为它是不可变的)。在某些上下文中速度更快,可用于索引等。
如果专门处理纯空格字符,请进一步简化:
CREATE FUNCTION trim_all2(text[])
RETURNS text[] AS
$func$
SELECT ARRAY (
SELECT regexp_replace(trim(elem), ' +', ' ', 'g')
FROM unnest($1) elem
)
$func$ LANGUAGE sql IMMUTABLE;
正则表达式相对昂贵。如果您进一步了解到,连续的空格字符最多不超过n个,则可以使用simplereplace()
。几次连续通话更便宜。对于最多8个连续空格:
CREATE OR REPLACE FUNCTION trim_all3(text[])
RETURNS text[] AS
$func$
SELECT ARRAY (
SELECT replace(replace(replace(
trim(elem)
, ' ', ' ') -- 5
, ' ' , ' ') -- 3
, ' ' , ' ') -- 2
FROM unnest($1) elem
)
$func$ LANGUAGE sql IMMUTABLE;
在我对第9.5页的测试中,每一个都比上一个版本快,而上一个版本的速度是上一个版本的两倍多
相关的:
它是否保留了元素的原始顺序?
SQL标准将允许任何没有明确的orderby
的订单。但在这种简单的安排下,Postgres将保持元素的原始顺序。
请在此处阅读更多信息:
感谢您的第一个和第二个答案。这很有效(而且很有意义)!有趣。array(…)
版本是否保留数组中元素的顺序?@a_horse_,其名称为:是,但SQL标准不保证这一点。这是一个实现细节——对于简单的情况来说,这不会改变。我选择数组_agg()
的原因是因为我可以通过序数
和order by
@a_horse\u和_no_name来保留数组中原始条目的顺序:您可以对数组构造函数执行相同的操作。我只是选择放弃它,因为我们可以,这样可以节省一点时间。无论采用哪种方式,添加orderby
都更简洁。OP也没有明确指定是否需要保留元素的顺序。