common-lisp
Functies toewijzen aan lijsten
Zoeken…
Overzicht
Een set toewijzingsfuncties op hoog niveau is beschikbaar in Common Lisp om een functie toe te passen op de elementen van een of meer lijsten. Ze verschillen in de manier waarop de functie wordt toegepast op de lijsten en hoe het eindresultaat wordt verkregen. De volgende tabel vat de verschillen samen en toont voor elk van hen het equivalente LOOP-formulier. f is de functie die moet worden toegepast, die een aantal argumenten moet hebben gelijk aan het aantal lijsten; "Toegepast op auto" betekent dat het beurtelings wordt toegepast op de elementen van de lijsten, "toegepast op cdr" betekent dat het beurtelings wordt toegepast op de lijsten, hun cdr, hun cddr, enz .; de kolom "retouren" geeft aan of het globale resultaat is verkregen door de resultaten te vermelden, ze samen te voegen (het moeten dus lijsten zijn!) of eenvoudigweg worden gebruikt voor bijwerkingen (en in dit geval wordt de eerste lijst geretourneerd).
Functie | Toegepast op | Geeft terug | Gelijkwaardige LUS |
---|---|---|---|
(mapcar fl 1 ... l n ) | auto | lijst met resultaten | (lus voor x 1 in l 1 ... voor x n in l n collect (fx 1 ... x n )) |
(maplist fl 1 ... l n ) | cdr | lijst met resultaten | (lus voor x 1 op l 1 ... voor x n op l n collect (fx 1 ... x n )) |
(mapcan fl 1 ... l n ) | auto | samenvoeging van resultaten | (lus voor x 1 in l 1 ... voor x n in l n nconc (fx 1 ... x n )) |
(mapcon fl 1 ... l n ) | cdr | samenvoeging van resultaten | (lus voor x 1 op l 1 ... voor x n op l n nconc (fx 1 ... x n )) |
(mapc fl 1 ... l n ) | auto | l 1 | (lus voor x 1 in l 1 ... voor x n in l n do (fx 1 ... x n ) tot slot (return l 1 )) |
(mapl fl 1 ... l n ) | cdr | l 1 | (lus voor x 1 op l 1 ... voor x n op l n do (fx 1 ... x n ) tot slot (return l 1 )) |
Merk op dat in alle gevallen de lijsten verschillende lengtes kunnen hebben en de toepassing wordt beëindigd wanneer de kortste lijst wordt beëindigd.
Er zijn nog een paar mapcar
beschikbaar: map
, die kan worden toegepast op reeksen (tekenreeksen, vectoren, lijsten), analoog aan mapcar
, en die elk type reeks kan teruggeven, gespecificeerd als eerste argument, en map-into
, analoog aan map
, maar dat wijzigt zijn eerste reeksargument destructief om de resultaten van de toepassing van de functie te behouden.
Voorbeelden van MAPCAR
MAPCAR is de meest gebruikte functie van de familie:
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)
Een idiomatisch gebruik van mapcar
is het omzetten van een matrix weergegeven als een lijst met lijsten:
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 |
; +---+---+---+ +---+---+---+
Zie voor een toelichting dit antwoord .
Voorbeelden van 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))
Voorbeelden van MAPCAN en 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)
Een van de toepassingen van MAPCAN is het maken van een resultatenlijst zonder NIL-waarden:
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)
Voorbeelden van MAPC en 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)