Arrays 在文本数组上应用'trim()'和'regexp_replace()'

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

我正在尝试将PostgreSQL文本数组转换为一个数组,其中每个值都被一个值替换,其中每个空格的每一侧都由一个字符包围。换句话说,我试图对文本数组中的每个值应用
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个,则可以使用simple
replace()
。几次连续通话更便宜。对于最多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也没有明确指定是否需要保留元素的顺序。