Pregunta ¿Cómo se copia una matriz en el ceceo común?


Me gustaría hacer copias de mi matriz 2D, que se siente como la forma agradable, funcional y no destructiva de manejar arreglos. ¿Cuál es la forma lisa de hacer esto?


10
2017-10-27 06:04


origen


Respuestas:


Uso lo siguiente, que creo que es mejor que la versión de alexandria:

(defun copy-array (array &key
                   (element-type (array-element-type array))
                   (fill-pointer (and (array-has-fill-pointer-p array)
                                      (fill-pointer array)))
                   (adjustable (adjustable-array-p array)))
  "Returns an undisplaced copy of ARRAY, with same fill-pointer and
adjustability (if any) as the original, unless overridden by the keyword
arguments."
  (let* ((dimensions (array-dimensions array))
         (new-array (make-array dimensions
                                :element-type element-type
                                :adjustable adjustable
                                :fill-pointer fill-pointer)))
    (dotimes (i (array-total-size array))
      (setf (row-major-aref new-array i)
            (row-major-aref array i)))
    new-array))

El problema con la versión de Alejandría es que el adjust-array hack hace que el resultado (al menos en SBCL) nunca sea un simple-array, que algunas otras bibliotecas (por ejemplo, óptica) esperan. los la versión anterior también fue más rápida para mí.

Alguien más ha publicado una versión muy similar en otro biblioteca, pero olvidé los nombres de la persona y la biblioteca.


14
2017-10-27 19:57



La biblioteca Common Lisp Alejandría (instalable a través de quicklisp) incluye una implementación de copy-array para rangos arbitrarios y dimensiones:

(defun copy-array (array &key
                   (element-type (array-element-type array))
                   (fill-pointer (and (array-has-fill-pointer-p array)
                                      (fill-pointer array)))
                   (adjustable (adjustable-array-p array)))
  "Returns an undisplaced copy of ARRAY, with same fill-pointer and
adjustability (if any) as the original, unless overridden by the keyword
arguments. Performance depends on efficiency of general ADJUST-ARRAY in the
host lisp -- for most cases a special purpose copying function is likely to
perform better."
  (let ((dims (array-dimensions array)))
    ;; Dictionary entry for ADJUST-ARRAY requires adjusting a
    ;; displaced array to a non-displaced one to make a copy.
    (adjust-array
     (make-array dims
                 :element-type element-type :fill-pointer fill-pointer
                 :adjustable adjustable :displaced-to array)
     dims)))

3
2017-10-27 10:49



Depende de cómo esté representada su matriz 2D y qué sabor de Lisp está usando.

Si está utilizando Common Lisp, entonces copia-seq Podría ser útil.


1
2017-10-27 06:14



Si quieres hacer cosas the nice, functional, nondestructive way, entonces ¿por qué necesitas copiarlo?

  • si lo está copiando para actualizarlo, entonces no lo está haciendo de manera funcional.

  • si lo haces de manera funcional, entonces no necesitas una copia. Puedes pasarlo a cualquier lado y en todas partes.

Quizás quieras transformarlo. En ese caso, podría usar una de las muchas funciones puras de Lisp, como mapcar o filter.


0
2017-10-28 21:17