All of the map functions like mapcar
, mapcan
, mapc
, etc require lists as their inputs. I am working with 2D arrays, and would prefer to not mess with the rank of my arrays given the often large sizes (50,000 x 1,000 sometimes).
I need a way to apply a function like (log n)
to each element in the 2D array and yield a resulting 2D array.
Any help or direction is much appreciated.
Working in AllegroCL (Common Lisp)
What you need is a combination of
Something like this:
(defun array-map (function array
&optional (retval (make-array (array-dimensions array))))
"Apply FUNCTION to each element of ARRAY.
Return a new array, or write into the optional 3rd argument."
(dotimes (i (array-total-size array) retval)
(setf (row-major-aref retval i)
(funcall function (row-major-aref array i)))))
Example:
(defparameter a (make-array '(2 3) :initial-contents '((1 2 3) (4 5 6))))
a
==> #2A((1 2 3) (4 5 6))
(array-map #'sqrt a)
==> #2A((1 1.4142135 1.7320508) (2 2.236068 2.4494898))
a ; does not change!
==> #2A((1 2 3) (4 5 6))
You can also use array-map
similar to map-into
:
(array-map #'1+ a a)
==> #2A((2 3 4) (5 6 7))
a ; modified, no new storage is allocated
==> #2A((2 3 4) (5 6 7))
Note that array-map
will work on any array dimension, from vectors to matrices to 10d &c.
Exercise: implement array-multi-map
accepting a function of any number of argument and any number of arrays, so that
(array-multi-map #'+ #A((1 2 3) (4 5 6)) #A((11 22 33) (44 55 66)))
==> #A((12 24 36) (48 60 72))
PS. The whole CLHS Chapter 15 Arrays or CLtL2 Chapter 17 Arrays is worth studying.