На этом шаге мы рассмотрим задачи на обработку A-списков.
Ассоциативный список (A-список, список пар) - это фундаментальный тип данных, представляющий собой список точечных пар вида: ( (A1 . T1) (A2 . T2) ... (AN . TN) )
Первый элемент пары (CAR) называют ключом, а второй (CDR) - связанными с ключом данными. Обычно ключом является атом. Связанные с ним данные могут быть атомами, списками или какими-нибудь другими объектами языка LISP.
Приведем формальное определение A-списка в форме Бэкуса-Наура:
<Ассоциативный список> ::=
NIL | (<Точечная пара> . <Ассоциативный список>)
<Точечная пара> ::=
(<Атом> . <Атом>) | (<Атом> . <Точечная пара>) |
(<Точечная пара> . <Атом>) |
(<Точечная пара> . <Точечная пара>)
Приведем графическое представление A-списка:
Рис.1. Графическое представление A-списка
В работе со списками пар нужно уметь:
(DEFUN DEMO_1 (LAMBDA NIL ; Инициализация атомов A и B ; (SETQ A '(JAPAN USSR)) (SETQ B '(TOKIO MOSCOW)) (PRIN1 "Построим A-список из списков A и B: ") (PRINT (SETQ ALIST (PAIRLIS A B NIL))) ; ----------------------------------------- ; (PRIN1 "Проверим составные части A-списка: ") (PRINT (REKEY ALIST)) (PRINT (REDATA ALIST)) ; ------------------------------------------------- ; (PRIN1 "Найдем данные, соответствующие ключу USSR: ") (PRINT (ASSOC1 USSR ALIST)) (PRIN1 "Найдем данные, соответствующие ключу JAPAN: ") (PRINT (ASSOC1 JAPAN ALIST)) ; -------------------------------------------------- ; (PRIN1 "Найдем ключ, соответствующий данным MOSCOW: ") (PRINT (RASSOC MOSCOW ALIST)) ; -------------------------------------------------- ; (PRINT "Добавление в начало A-списка точечной пары: ") (PRINT (SETQ ALIST (ACONS USA WASHINGTON ALIST))) ; ---------------------------------------------------- ; (PRINT "Изменение данных, соответствующих ключу USSR: ") (PUTASSOC USSR SPB ALIST) )) ; ----------------------------------- ; (DEFUN PAIRLIS (LAMBDA (KEY DATA ALIST) ; Построение A-списка из списка ключей KEY и списка ; ; данных DATA путем добавления новых пар к существу- ; ; ющему списку ALIST ; ( (NULL KEY) ALIST ) ( (NULL DATA) ALIST ) ( CONS (CONS (CAR KEY) (CAR DATA)) (PAIRLIS (CDR KEY) (CDR DATA) ALIST) ) )) ; ----------------------------- ; (DEFUN ASSOC1 (LAMBDA (KEY ALIST) ; Поиск в списке пар ALIST данных, соответствующих ; ; ключу KEY ; (COND ( (NULL ALIST) NIL ) ( (EQ (CAAR ALIST) KEY) (CAR ALIST) ) ; Возвращается первая найденная пара, ; ; содержащая ключ KEY ; ( T (ASSOC1 KEY (CDR ALIST)) ) ) )) ; ------------------------------ ; (DEFUN RASSOC (LAMBDA (DATA ALIST) ; Поиск в списке пар ALIST ключа, соответствующего ; ; данным DATA ; (COND ( (NULL ALIST) NIL ) ( (EQ (CDAR ALIST) DATA) (CAR ALIST) ) ; Возвращается пара, содержащая данные DATA ; ( T (RASSOC DATA (CDR ALIST)) ) ) )) ; ---------------------------- ; (DEFUN ACONS (LAMBDA (X Y ALIST) ; Добавление в начало списка ALIST ; ; точечной пары (X . Y) ; (CONS (CONS X Y) ALIST) )) ; ------------------------------------ ; (DEFUN PUTASSOC (LAMBDA (KEY DATA ALIST) ; Изменение данных, соответствующих ключу KEY, ; ; на данные DATA ; ( (NULL ALIST) NIL ) ( (EQ (CAAR ALIST) KEY) (RPLACD (CAR ALIST) DATA) ) ( (NULL (CDR ALIST)) (RPLACD ALIST (LIST (CONS KEY DATA))) ) ; Добавление новой пары (KEY . DATA) ; ( PUTASSOC KEY DATA (CDR ALIST) ) )) ; ------------------------ ; (DEFUN REKEY (LAMBDA (ALIST) ; Восстановление списка ключей по известному А-списку ; (COND ( (NULL ALIST) NIL ) ( T (CONS (CAR (CAR ALIST)) (REKEY (CDR ALIST))) ) ) )) ; ------------------------- ; (DEFUN REDATA (LAMBDA (ALIST) ; Восстановление списка данных по известному А-списку ; (COND ( (NULL ALIST) NIL ) ( T (CONS (CDR (CAR ALIST)) (REDATA (CDR ALIST))) ) ) ))
(DEFUN DEMO_2 (LAMBDA NIL (PRINT "Построение ассоциативного списка:") (SETQ ALIST NIL) (LOOP (PRINT "Введите ключ (окончание ввода - !:") (SETQ KEY (READ)) ( (EQ KEY '!) ) (PRINT "Введите данное для этого ключа:") (SETQ DATA (READ)) (SETQ ALIST (ACONS KEY DATA ALIST)) ) ; Взглянем на ассоциативный список (PRINT "Ассоциативный список:") (PRINT ALIST) )) ; ------------------------------ (DEFUN ACONS (LAMBDA (X Y ALIST) ; Добавление в начало списка ALIST ; точечной пары (X . Y) (CONS (CONS X Y) ALIST) ))
На следующем шаге мы приведем задачи на использование списков свойств.