Re: Subtract one array from another, both with non-unique elements

Поиск
Список
Период
Сортировка
От Alexander Farber
Тема Re: Subtract one array from another, both with non-unique elements
Дата
Msg-id CAADeyWgUbqu6L1rnu5ebixv9hwjf_7Yde9Rf4B7NctOkkYjRbg@mail.gmail.com
обсуждение исходный текст
Ответ на Re: Subtract one array from another, both with non-unique elements  (Pavel Stehule <pavel.stehule@gmail.com>)
Ответы Re: Subtract one array from another, both with non-unique elements  (Alexander Farber <alexander.farber@gmail.com>)
Список pgsql-general
So I have written my own stored function
to subtract one non-unique array from another
(like swapping tiles in a word game):

DROP FUNCTION IF EXISTS words_array_subtract(anyarray, anyarray);
CREATE OR REPLACE FUNCTION words_array_subtract(from_array anyarray, remove_array anyarray)
        RETURNS anyarray AS
$func$
        DECLARE
                i integer;
                j integer;
                from_ignore boolean[];
                remove_ignore boolean[];
                result_array from_array%TYPE := '{}';
        BEGIN
                IF NOT from_array @> remove_array THEN
                        RAISE EXCEPTION '% does not contain %', from_array, remove_array;
                END IF;

                from_ignore   := ARRAY_FILL(FALSE, ARRAY[ARRAY_LENGTH(from_array, 1)]);
                remove_ignore := ARRAY_FILL(FALSE, ARRAY[ARRAY_LENGTH(remove_array, 1)]);

                RAISE NOTICE 'from_ignore = %', from_ignore;
                RAISE NOTICE 'remove_ignore = %', remove_ignore;

                FOR i IN ARRAY_LOWER(from_array, 1)..ARRAY_UPPER(from_array, 1) LOOP
                        FOR j IN ARRAY_LOWER(remove_array, 1)..ARRAY_UPPER(remove_array, 1) LOOP
                                IF from_ignore[i] = FALSE AND
                                   remove_ignore[j] = FALSE AND
                                   from_array[i] = remove_array[j] THEN
                                        from_ignore[i] := TRUE;
                                        remove_ignore[j] := TRUE;
                                END IF;
                        END LOOP;
                END LOOP;

                FOR i IN ARRAY_LOWER(from_array, 1)..ARRAY_UPPER(from_array, 1) LOOP
                        IF from_ignore[i] = FALSE THEN
                                result_array := ARRAY_APPEND(result_array, from_array[i]);
                        END IF;
                END LOOP;

                RETURN result_array;
        END;
$func$ LANGUAGE plpgsql;

# select words_array_subtract(ARRAY['A','A','B','B','C'], ARRAY['A','B']);
NOTICE:  from_ignore = {f,f,f,f,f}
NOTICE:  remove_ignore = {f,f}
 words_array_subtract
----------------------
 {A,B,C}
(1 row)

# select words_array_subtract(ARRAY[1,2,2,3,4,4, 5], ARRAY[2,4,4]);
NOTICE:  from_ignore = {f,f,f,f,f,f,f}
NOTICE:  remove_ignore = {f,f,f}
 words_array_subtract
----------------------
 {1,2,3,5}
(1 row)


If you have any improvement proposals please tell me.

Regards
Alex

В списке pgsql-general по дате отправления:

Предыдущее
От: Berend Tober
Дата:
Сообщение: Re: Logger into table and/or to cli
Следующее
От: Alexander Farber
Дата:
Сообщение: Re: Subtract one array from another, both with non-unique elements