common-lisp
Mappage des fonctions sur les listes
Recherche…
Vue d'ensemble
Un ensemble de fonctions de cartographie de haut niveau est disponible dans Common Lisp, pour appliquer une fonction aux éléments d'une ou de plusieurs listes. Ils diffèrent dans la manière dont la fonction est appliquée aux listes et comment le résultat final est obtenu. Le tableau suivant récapitule les différences et montre pour chacun d'eux le formulaire LOOP équivalent. f est la fonction à appliquer, qui doit avoir un nombre d'arguments égal au nombre de listes; "Appliqué à la voiture" signifie qu'il est appliqué à son tour aux éléments des listes, "appliqué au cdr" signifie qu'il est appliqué à son tour aux listes, à leur cdr, à leur cddr, etc. la colonne «retourne» indique si le résultat global est obtenu en listant les résultats, en les concaténant (ils doivent donc être des listes!) ou simplement en utilisant des effets secondaires (et dans ce cas la première liste est renvoyée).
Fonction | Appliqué à | Résultats | LOOP équivalente |
---|---|---|---|
(mapcar fl 1 ... l n) | voiture | liste des résultats | (boucle pour x 1 en l 1 … pour x n en l n collect (fx 1 … x n )) |
(maplist fl 1 … l n ) | cdr | liste des résultats | (boucle pour x 1 sur l 1 … pour x n sur l n collect (fx 1 … x n )) |
(mapcan fl 1 … l n ) | voiture | concaténation des résultats | (boucle pour x 1 en l 1 … pour x n en l n nconc (fx 1 … x n )) |
(mapcon fl 1 … l n ) | cdr | concaténation des résultats | (boucle pour x 1 sur l 1 … pour x n sur l n nconc (fx 1 … x n )) |
(mapc fl 1 … l n ) | voiture | l 1 | (boucle pour x 1 en l 1 … pour x n en l n do (fx 1 … x n ) enfin (retour l 1 )) |
(mapl fl 1 … l n ) | cdr | l 1 | (boucle pour x 1 sur l 1 … pour x n sur l n do (fx 1 … x n ) enfin (retour l 1 )) |
Notez que, dans tous les cas, les listes peuvent avoir des longueurs différentes et que l'application se termine lorsque la liste la plus courte est terminée.
Un autre couple de fonctions cartographiques est disponible: la map
, qui peut être appliquée à des séquences (chaînes, vecteurs, listes), analogue à mapcar
, et qui peut renvoyer tout type de séquence, spécifié comme premier argument, et map-into
, analogue à map
, mais cela modifie de façon destructive son premier argument de séquence pour conserver les résultats de l'application de la fonction.
Exemples de MAPCAR
MAPCAR est la fonction la plus utilisée de la famille:
CL-USER> (mapcar #'1+ '(1 2 3))
(2 3 4)
CL-USER> (mapcar #'cons '(1 2 3) '(a b c))
((1 . A) (2 . B) (3 . C))
CL-USER> (mapcar (lambda (x y z) (+ (* x y) z))
'(1 2 3)
'(10 20 30)
'(100 200 300))
(110 240 390)
CL-USER> (let ((list '(a b c d e f g h i))) ; randomize this list
(mapcar #'cdr
(sort (mapcar (lambda (x)
(cons (random 100) x))
list)
#'<=
:key #'car)))
(I D A G B H E C F)
Une utilisation idiomatique de mapcar
consiste à transposer une matrice représentée par une liste de listes:
CL-USER> (defun transpose (list-of-lists)
(apply #'mapcar #'list list-of-lists))
ROTATE
CL-USER> (transpose '((a b c) (d e f) (g h i)))
((A D G) (B E H) (C F I))
; +---+---+---+ +---+---+---+
; | A | B | C | | A | D | G |
; +---+---+---+ +---+---+---+
; | D | E | F | becomes | B | E | H |
; +---+---+---+ +---+---+---+
; | G | H | I | | C | F | I |
; +---+---+---+ +---+---+---+
Pour une explication, voir cette réponse .
Exemples de MAPLIST
CL-USER> (maplist (lambda (list) (cons 0 list)) '(1 2 3 4))
((0 1 2 3 4) (0 2 3 4) (0 3 4) (0 4))
CL-USER> (maplist #'append
'(a b c d -)
'(1 2 3))
((A B C D - 1 2 3) (B C D - 2 3) (C D - 3))
Exemples de MAPCAN et MAPCON
MAPCAN:
CL-USER> (mapcan #'reverse '((1 2 3) (a b c) (100 200 300)))
(3 2 1 C B A 300 200 100)
CL-USER> (defun from-to (min max)
(loop for i from min to max collect i))
FROM-TO
CL-USER> (from-to 1 5)
(1 2 3 4 5)
CL-USER> (mapcan #'from-to '(1 2 3) '(5 5 5))
(1 2 3 4 5 2 3 4 5 3 4 5)
L'une des utilisations de MAPCAN consiste à créer une liste de résultats sans valeurs NIL:
CL-USER> (let ((l1 '(10 20 40)))
(mapcan (lambda (x)
(if (member x l1)
(list x)
nil))
'(2 4 6 8 10 12 14 16 18 20
18 16 14 12 10 8 6 4 2)))
(10 20 10)
MAPCON:
CL-USER> (mapcon #'copy-list '(1 2 3))
(1 2 3 2 3 3)
CL-USER> (mapcon (lambda (l1 l2) (list (length l1) (length l2))) '(a b c d) '(d e f))
(4 3 3 2 2 1)
Exemples de MAPC et MAPL
MAPC:
CL-USER> (mapc (lambda (x) (print (* x x))) '(1 2 3 4))
1
4
9
16
(1 2 3 4)
CL-USER> (let ((sum 0))
(mapc (lambda (x y) (incf sum (* x y)))
'(1 2 3)
'(100 200 300))
sum)
1400 ; => (1 x 100) + (2 x 200) + (3 x 300)
MAPL:
CL-USER> (mapl (lambda (list) (print (reduce #'+ list))) '(1 2 3 4 5))
15
14
12
9
5
(1 2 3 4 5)