14.3 Модификация последовательностей

Каждая из этих функций или модифицирует последовательность, или возвращает модифицированную копию.

[Функция] fill sequence item &key :start :end

Функция модифицирует последовательность, заменяя каждый элемент подпоследовательности, обозначенной с помощью параметров :start и :end, объектом item. item может быть любым Lisp’овыми объектом, подходящим для типа элементов последовательности sequence. Объект item сохраняется в всех указанных компонентах последовательности sequence, начиная с позиции :start (по-умолчанию равна 0) и заканчивая невключительно позицией :end (по-умолчанию равна длине последовательности). fill возвращает изменённую последовательность. Например:

(setq x (vector ’a ’b ’c ’d ’e))  #(a b c d e)
(fill x ’z :start 1 :end 3)  #(a z z d e)
  and now x  #(a z z d e)
(fill x ’p)  #(p p p p p)
  and now x  #(p p p p p)


[Функция] replace sequence1 sequence2 &key :start1 :end1 :start2 :end2

Функция модифицирует последовательность sequence1 копируя в неё элементы из последовательности sequence2. Элементы sequence2 должны принадлежать типу элементов sequence1. Подпоследовательность sequence2, указанная с помощью параметров :start2 и :end2, копируется в подпоследовательность sequence2, указанную с помощью параметров :start1 и :end1. Аргументы :start1 и :start2 по-умолчанию равны нулю. Аргументы :end1 и :end2 по-умолчанию nil, что означает длины соответствующих последовательностей. Если указанные подпоследовательности имеют не равные длины, тогда для наиболее короткая из них определяет копируемые элементы. Лишние элементы последовательностей функцией не обрабатываются. Количество копируемых элементов можно вычислить так:

(min (- end1 start1) (- end2 start2))

Значением функции replace является модифицированная последовательность sequence1.

Если обе последовательности равны (eq), и интервал для модификации перекрывается с исходным интервалом, тогда поведение такое, как если бы все исходные данные сохранялись во временном месте, а затем сохранялись в итоговый интервал. Однако, если последовательности не равны, но итоговый интервал пересекается с исходным (возможно, при использовании соединённых массивов), тогда после выполнения replace, итоговое содержимое не определено.


[Функция] remove item sequence &key :from-end :test :test-not :start :end :count :key
[Функция] remove-if predicate sequence &key :from-end :start :end :count :key
[Функция] remove-if-not predicate sequence &key :from-end :start :end :count :key

Результатом является последовательность того же типа, что и последовательность sequence. Однако, итоговая последовательность не будет содержать элементы в интервале :start-:end, которые удовлетворяли условию. Результат является копией входящей последовательности sequence без исключённых элементов. Неудалённые элементы сохраняются в таком же порядке.

Если указан аргумент :count, то удаляться будет только это количество. Если количество удаляемых элементов превышает параметр, тогда будут удалены только самые левые в количестве равном :count.

X3J13 voted in January 1989 to clarify that the :count argument must be either nil or an integer, and that supplying a negative integer produces the same behavior as supplying zero.

Если при использовании :count для параметра :from-end указано не-nil значение, тогда удаление элементов будет происходить справа в количестве :count. Например:

(remove 4 ’(1 2 4 1 3 4 5))  (1 2 1 3 5)
(remove 4 ’(1 2 4 1 3 4 5) :count 1)  (1 2 1 3 4 5)
(remove 4 ’(1 2 4 1 3 4 5) :count 1 :from-end t)
    (1 2 4 1 3 5)
(remove 3 ’(1 2 4 1 3 4 5) :test #’>)  (4 3 4 5)
(remove-if #’oddp ’(1 2 4 1 3 4 5))  (2 4 4)
(remove-if #’evenp ’(1 2 4 1 3 4 5) :count 1 :from-end t)
    (1 2 4 1 3 5)

Результат remove может быть соединён с исходной последовательностью. Также результат может быть равен eq исходной последовательности, если ни одного элементы не было удалено.

X3J13 voted in January 1989 to restrict user side effects; see section 7.9.

Пользователь ограничен в создании побочных действий так, как это описано в разделе 7.9


[Функция] delete item sequence &key :from-end :test :test-not :start :end :count :key
[Функция] delete-if predicate sequence &key :from-end :start :end :count :key
[Функция] delete-if-not predicate sequence &key :from-end :start :end :count :key

Данная функция в отличие от remove модифицирует исходную последовательность. Результатом является последовательность того же типа, что и последовательность sequence. Однако, итоговая последовательность не будет содержать элементы в интервале :start-:end, которые удовлетворяли условию. Результат является копией входящей последовательности sequence без исключённых элементов. Неудалённые элементы сохраняются в таком же порядке. Последовательность sequence может быть модифицирована, поэтому результат может быть равен eq или нет исходной последовательности.

Если указан аргумент :count, то удаляться будет только это количество. Если количество удаляемых элементов превышает параметр, тогда будут удалены только самые левые в количестве равном :count.

X3J13 voted in January 1989 to clarify that the :count argument must be either nil or an integer, and that supplying a negative integer produces the same behavior as supplying zero.

Если при использовании :count для параметра :from-end указано не-nil значение, тогда удаление элементов будет происходить справа в количестве :count. Например:

(delete 4 ’(1 2 4 1 3 4 5))  (1 2 1 3 5)
(delete 4 ’(1 2 4 1 3 4 5) :count 1)  (1 2 1 3 4 5)
(delete 4 ’(1 2 4 1 3 4 5) :count 1 :from-end t)
    (1 2 4 1 3 5)
(delete 3 ’(1 2 4 1 3 4 5) :test #’>)  (4 3 4 5)
(delete-if #’oddp ’(1 2 4 1 3 4 5))  (2 4 4)
(delete-if #’evenp ’(1 2 4 1 3 4 5) :count 1 :from-end t)
    (1 2 4 1 3 5)

X3J13 voted in January 1989 to restrict user side effects; see section 7.9.

Пользователь ограничен в создании побочных действий так, как это описано в разделе 7.9

X3J13 voted in March 1989 to clarify the permissible side effects of certain operations. When the sequence is a list, delete is permitted to perform a setf on any part, car or cdr, of the top-level list structure of that list. When the sequence is an array, delete is permitted to alter the dimensions of the given array and to slide some of its elements into new positions without permuting them in order to produce the resulting array.

Furthermore, (delete-if predicate sequence ...) is required to behave exactly like

(delete nil sequence
        :test #’(lambda (unused item)
                   (declare (ignore unused))
                   (funcall predicate item))
        ...)


[Функция] remove-duplicates sequence &key :from-end :test :test-not :start :end :key
[Функция] delete-duplicates sequence &key :from-end :test :test-not :start :end :key

Функция попарно сравнивает элементы последовательности sequence, и если они равны, тогда первый из них удаляется (если параметр :from-end равен истине, то удаляется последний). Результат является последовательностью того же типа, что и исходная, с удалёнными повторяющимися элементами. Порядок следования элементов в итоге такой же как в исходной последовательности.

remove-duplicates является не модифицирующей версией этой операции. Результат remove-duplicates может быть соединён с исходной последовательностью. Также результат может быть равен eq исходной последовательности, если ни одного элементы не было удалено.

delete-duplicates может модифицировать аргумент sequence.

Например:

(remove-duplicates ’(a b c b d d e))  (a c b d e)
(remove-duplicates ’(a b c b d d e) :from-end t)  (a b c d e)
(remove-duplicates ’((foo #\a) (bar #\%) (baz #\A))
                   :test #’char-equal :key #’cadr)
    ((bar #\%) (baz #\A))
(remove-duplicates ’((foo #\a) (bar #\%) (baz #\A))
                   :test #’char-equal :key #’cadr :from-end t)
    ((foo #\a) (bar #\%))

Эти функции полезны для преобразования последовательности в каноническую форму представления множества.

X3J13 voted in January 1989 to restrict user side effects; see section 7.9.

Пользователь ограничен в создании побочных действий так, как это описано в разделе 7.9

X3J13 voted in March 1989 to clarify the permissible side effects of certain operations. When the sequence is a list, delete-duplicates is permitted to perform a setf on any part, car or cdr, of the top-level list structure of that list. When the sequence is an array, delete-duplicates is permitted to alter the dimensions of the given array and to slide some of its elements into new positions without permuting them in order to produce the resulting array.


[Функция] substitute newitem olditem sequence &key :from-end :test :test-not :start :end :count :key
[Функция] substitute-if newitem test sequence &key :from-end :start :end :count :key
[Функция] substitute-if-not newitem test sequence &key :from-end :start :end :count :key

Результатом является последовательность такого же типа что и исходная sequence за исключением того, что удовлетворяющие условию элементы в интервале :start-:end будут заменены на объект newitem. Эта операция создаёт копию исходной последовательности с некоторыми изменёнными элементами.

Если указан аргумент :count, то изменяться будет только это количество элементов. Если количество изменяемых элементов превышает параметр, тогда будут удалены только самые левые в количестве равном :count.

X3J13 voted in January 1989 to clarify that the :count argument must be either nil or an integer, and that supplying a negative integer produces the same behavior as supplying zero.

Если при использовании :count для параметра :from-end указано не-nil значение, тогда изменение элементов будет происходить справа в количестве :count. Например:

(substitute 9 4 ’(1 2 4 1 3 4 5))  (1 2 9 1 3 9 5)
(substitute 9 4 ’(1 2 4 1 3 4 5) :count 1)  (1 2 9 1 3 4 5)
(substitute 9 4 ’(1 2 4 1 3 4 5) :count 1 :from-end t)
    (1 2 4 1 3 9 5)
(substitute 9 3 ’(1 2 4 1 3 4 5) :test #’>)  (9 9 4 9 3 4 5)
(substitute-if 9 #’oddp ’(1 2 4 1 3 4 5))  (9 2 4 9 9 4 9)
(substitute-if 9 #’evenp ’(1 2 4 1 3 4 5) :count 1 :from-end t)
    (1 2 4 1 3 9 5)

Результат substitute может быть соединён с исходной последовательностью. Также результат может быть равен eq исходной последовательности, если ни одного элементы не было изменено.

Смотрите также subst, которая осуществляет замену в древовидной структуре.

X3J13 voted in January 1989 to restrict user side effects; see section 7.9.

Пользователь ограничен в создании побочных действий так, как это описано в разделе 7.9


[Функция] nsubstitute newitem olditem sequence &key :from-end :test :test-not :start :end :count :key
[Функция] nsubstitute-if newitem test sequence &key :from-end :start :end :count :key
[Функция] nsubstitute-if-not newitem test sequence &key :from-end :start :end :count :key

Эта функция является деструктивным аналогом для substitute. Это значит, что они модифицирует свой аргумент. Результатом является последовательность такого же типа что и исходная sequence за исключением того, что удовлетворяющие условию элементы в интервале :start-:end будут заменены на объект newitem. Последовательность sequence может быть модифицирована, поэтому результат может быть равен eq или нет исходной последовательности.

Смотрите также nsubst, которая осуществляет деструктивную замену в древовидной структуре.

X3J13 voted in January 1989 to restrict user side effects; see section 7.9.

X3J13 voted in March 1989 to clarify the permissible side effects of certain operations. When the sequence is a list, nsubstitute or nsubstitute-if is required to perform a setf on any car of the top-level list structure of that list whose old contents must be replaced with newitem but is forbidden to perform a setf on any cdr of the list. When the sequence is an array, nsubstitute or nsubstitute-if is required to perform a setf on any element of the array whose old contents must be replaced with newitem. These functions, therefore, may successfully be used solely for effect, the caller discarding the returned value (though some programmers find this stylistically distasteful).