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

时间:2016-08-30 20:05:21

标签: arrays postgresql plpgsql trim

我正在尝试将PostgreSQL文本数组转换为一个值,其中每个值都被替换为每个空格被每边的字符包围的值。换句话说,我正在尝试对文本数组中的每个值应用trim()regexp_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 ", " Ye llow "}'作为参数之一调用函数时,返回的值是完全相同的文本数组。如何将'{"red", "blue", "yellow"}'作为返回值?

我一直在盯着trim()regexp_replace()FOREACH循环的定义,我可能只需要别人检查。

2 个答案:

答案 0 :(得分:1)

您的代码永远不会更改multiplevalues数组。它只是改变了每个元素,然后抛弃了新的价值。

您需要一个变量,您可以将结果汇总到:

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;

但是使用unfst和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;

答案 1 :(得分:1)

还有一些改进:

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;

如果您专门处理普通空格字符,请进一步简化:

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 ,则可以使用简单的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;

在我对pg 9.5的测试中,每个测试都比前一个版本快,最后一个版本的速度是@a_horse's function的两倍。

相关:

它是否保留元素的原始顺序?

SQL标准允许任何订单而不显式ORDER BY。但是在这个简单的安排中,Postgres将保持元素的原始顺序。 在这里阅读更多内容: