common-lisp
Kartlägga funktioner över listor
Sök…
Översikt
En uppsättning mappningsfunktioner på hög nivå finns i Common Lisp för att tillämpa en funktion på elementen i en eller flera listor. De skiljer sig åt på vilket sätt funktionen tillämpas på listorna och hur det slutliga resultatet erhålls. Följande tabell sammanfattar skillnaderna och visar för var och en av dem motsvarande LOOP-form. f är den funktion som ska tillämpas, som måste ha ett antal argument lika med antalet listor; "Tillämpas på bil" betyder att det tillämpas i tur och ordning på elementen i listorna, "tillämpas på cdr" betyder att det tillämpas i tur och ordning på listorna, deras cdr, deras cddr osv .; kolumnen "returnerar" visar om det globala resultatet erhålls genom att lista resultaten, sammanfoga dem (så de måste vara listor!) eller helt enkelt användas för biverkningar (och i detta fall returneras den första listan).
Fungera | Appliceras på | Returer | Motsvarande LOOP |
---|---|---|---|
(kartbil fl 1 ... l n ) | bil | lista över resultat | (slinga för x 1 i l 1 ... för x n i l n samla (fx 1 ... x n )) |
(kartlista fl 1 ... l n ) | CDR | lista över resultat | (slinga för x 1 på l 1 ... för x n på l n samla (fx 1 ... x n )) |
(mapcan fl 1 ... l n ) | bil | sammanlänkning av resultat | (slinga för x 1 i l 1 ... för x n i l n nconc (fx 1 ... x n )) |
(mapcon fl 1 ... l n ) | CDR | sammanlänkning av resultat | (slinga för x 1 på l 1 ... för x n på l n nconc (fx 1 ... x n )) |
(mapc fl 1 ... l n ) | bil | l 1 | (slinga för x 1 i l 1 ... för x n i l n do (fx 1 ... x n ) äntligen (retur l 1 )) |
(mapl fl 1 ... l n ) | CDR | l 1 | (slinga för x 1 på l 1 ... för x n på l n do (fx 1 ... x n ) äntligen (retur l 1 )) |
Observera att listorna i alla fall kan ha olika längder och applikationen avslutas när den kortaste listan avslutas.
Ytterligare ett par kartfunktioner är tillgängliga: map
, som kan tillämpas på sekvenser (strängar, vektorer, listor), analog till mapcar
, och som kan returnera alla typer av sekvenser, specificerade som första argument, och map-into
, analog till map
, men det ändrar destruktivt sitt första sekvensargument för att behålla resultaten av tillämpningen av funktionen.
Exempel på MAPCAR
MAPCAR är familjens mest använda funktion:
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)
En idiomatisk användning av mapcar
är att transponera en matris representerad som en lista med listor:
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 |
; +---+---+---+ +---+---+---+
För att få en förklaring, se detta svar .
Exempel på 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))
Exempel på MAPCAN och 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)
En av användningarna av MAPCAN är att skapa en resultatlista utan NIL-värden:
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)
Exempel på MAPC och 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)