common-lisp
Funkcje mapowania na listach
Szukaj…
Przegląd
Zestaw funkcji mapowania wysokiego poziomu jest dostępny w Common Lisp, aby zastosować funkcję do elementów jednej lub więcej list. Różnią się sposobem, w jaki funkcja jest stosowana do list oraz sposobem uzyskania końcowego wyniku. Poniższa tabela podsumowuje różnice i pokazuje dla każdej z nich równoważny formularz PĘTLI. f jest funkcją do zastosowania, która musi mieć liczbę argumentów równą liczbie list; „Stosowane do samochodu” oznacza, że jest stosowane kolejno do elementów list, „stosowane do cdr” oznacza, że jest stosowane z kolei do list, ich cdr, ich cddr itp .; kolumna „zwroty” pokazuje, czy wynik globalny jest uzyskiwany przez wyświetlenie listy wyników, konkatenację (więc muszą to być listy!), czy też po prostu użycie ich do efektów ubocznych (w tym przypadku zwracana jest pierwsza lista).
Funkcjonować | Zastosowano do | Zwroty | Równoważna pętla |
---|---|---|---|
(mapcar fl 1 … l n ) | samochód | lista wyników | (pętla dla x 1 w l 1 … dla x n w l n zbierać (fx 1 … x n )) |
(maplist fl 1 … l n ) | cdr | lista wyników | (pętla dla x 1 na l 1 … dla x n na l n zbierać (fx 1 … x n )) |
(mapcan fl 1 … l n ) | samochód | łączenie wyników | (pętla dla x 1 in l 1 … dla x n in l n nconc (fx 1 … x n )) |
(mapcon fl 1 … l n ) | cdr | łączenie wyników | (pętla dla x 1 na l 1 … dla x n na l n nconc (fx 1 … x n )) |
(mapc fl 1 … l n ) | samochód | l 1 | (pętla dla x 1 w l 1 … dla x n w l n do (fx 1 … x n ) na końcu (zwróć l 1 )) |
(mapl fl 1 … l n ) | cdr | l 1 | (pętla dla x 1 na l 1 … dla x n na l n do (fx 1 … x n ) na końcu (zwróć l 1 )) |
Zauważ, że we wszystkich przypadkach listy mogą mieć różne długości, a aplikacja kończy się, gdy lista najkrótsza zostanie zakończona.
Dostępnych jest jeszcze kilka funkcji map: map
, którą można zastosować do sekwencji (ciągi, wektory, listy), analogicznie do mapcar
, i która może zwrócić dowolny typ sekwencji, określony jako pierwszy argument, i map-into
, analogicznie do map
, ale to destrukcyjnie modyfikuje argument pierwszej sekwencji, aby zachować wyniki zastosowania funkcji.
Przykłady MAPCAR
MAPCAR jest najczęściej używaną funkcją rodziny:
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)
mapcar
zastosowaniem mapcar
jest transponowanie macierzy reprezentowanej jako lista list:
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 |
; +---+---+---+ +---+---+---+
Aby uzyskać wyjaśnienie, zobacz tę odpowiedź .
Przykłady MAPLISTY
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))
Przykłady MAPCAN i 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)
Jednym z zastosowań MAPCAN jest utworzenie listy wyników bez wartości 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)
Przykłady MAPC i 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)