Лекция 4. Списки | [ИУ9] Основы информатики
LISP — List processing, обработка списков. Список — основная структура данных языка Scheme.
(1 2 3 4) — список из четырёх чисел.
Создание списка
(list <элементы>) (list 1 2 3 4) → (1 2 3 4) (list) → ()
Операции над списками:
cons
— конструирование(cons <голова> <хвост>) → <список>
Создаёт новый список из некоторого значения («головы») и другого списка («хвоста»). Первым элементом нового списка будет «голова», последующими — хвост.
(cons 1 (list 2 3 4)) → (1 2 3 4)
car
, cdr
, null?
(car <список>) → <голова списка> (cdr <список>) → <хвост списка> (null? <список>) → <bool>
Это селекторы, запрашивают голову и хвост списка, список должен быть непустым.
(car (list 1 2 3 4)) → 1 (cdr (list 1 2 3 4)) → (2 3 4) (null? (list 1 2 3 4)) → #f (null? (list)) → #t
Пустой список, запись списка через цитирование
'() — пустой список
Запись списка при помощи цитирования:
'(1 (2 3 4) 5 6)
Вложенные списки:
(list (list 1 2 3) (list 4 5 6)) → ((1 2 3) (4 5 6)) '((1 2 3) (4 5 6)) → ((1 2 3) (4 5 6))
Список можно связать с переменной:
(define L '(1 2 3)) (define x 1) (define (f y) (list x y)) (define (f y) (cons x (cons y '()))) '(x y)
Встроенная функция length
(length '(1 1 2 1)) → 4
Встроенная функция append
— конкатенация списков:
(append '(1 2 3) '(4 5 6)) → (1 2 3 4 5 6) (append '(1 2) '(3 4) '(5 6)) → (1 2 3 4 5 6)
Объект, который строится функцией cons
— т. н. cons-ячейка или пара. Аргументами функции cons
могут быть любые объекты.
Правильный список — это или пустой список, или cons-пара, вторым элементом которой является правильный список.
(cons 1 2) → (1 . 2) ;; неправильный список (cons 1 (cons 2 '())) → (1 2) ;; правильный список (cons 1 (cons 2 (cons 3 4))) → (1 2 3 . 4) ;; тоже неправильный список
Пример. Как могла бы быть определена встроенная функция length
:
(define (length xs) (if (null? xs) 0 (+ 1 (length (cdr xs))))) (define (length xs) (define (loop len xs) (if (null? xs) len (loop (+ len 1) (cdr xs)))) (loop 0 xs))
Функция pair?
возвращает истину, если аргумент — cons-ячейка.
Используется для того, чтобы единообразно преобразовать все элементы списка, принимает процедуру и исходный список, строит новый список той же длины, что и исходный, каждый элемент этого списка является результатом применения процедуры к элементу исходного списка.
(define (square x) (* x x)) (map square '(1 2 3 4 5)) → '(1 4 9 16 25)
Расширенный вариант использования
:
(map (lambda (x y) (+ (* 2 x) (* 3 y))) '(1 2 1 2) '(2 3 2 3 2) ) → '(8 13 8 13)
Функцию map
(«простой вариант») можно описать как:
(define (map f xs) (if (null? xs) '() (cons (f (car xs)) (map f (cdr xs)))))
Безымянная процедура, принимающая произвольное число аргументов:
(lambda xs …)
xs
— список аргументов
((lambda xs xs) 1 2 3 4) → (1 2 3 4)
Безымянная процедура, принимающая n+ аргументов:
(lambda (a b c . xs) …) ((lambda (a b c . xs) (list (+ a b c) xs)) 1 2 3 4 5) → (6 (4 5))
Именованная процедура:
(define (f <фиксированные параметры> . <список параметров>) …) (define (f a b c . xs) (list (+ a b c) xs)) (f 1 2 3 4 5) → (6 (4 5)) (define (f . xs) (list xs xs)) (f 1 2 3) → ((1 2 3) (1 2 3))
Функцию list
можно описать так:
(define (list . xs) xs)
Пример:
((lambda x x)) → ()
Вычислительная сложность — асимптотическая оценка времени работы программы. Асимптотическая, значит, нас интересует не конкретное время, а поведение.
T(<данные>)
— функция, возвращающая точное значение времени работы программы
на конкретных входных данных.
Асимптотическая оценка O(f(<данные>))
показывает, что функция T(•)
при росте входных
данных ведёт себя как функция f(•)
с точностью до некоторого постоянного сомножителя.
Т.е. существует такое k
, что
T(data) <= k×f(data)
при росте аргумента data
.
Оценку вычислительной сложности для некоторого алгоритма и некоторого абстрактного вычислителя обычно оценивают в числе элементарных команд этого абстрактного вычислителя.
Для Scheme элементарными операциями считаются вызов функции, cons
,
, cdr
,
получение значения переменной, создание процедуры (lambda
), объявление глобальной
переменной (define
), присваивание переменной (set!
), арифметические действия
с фиксированным числом операндов (не свёртка!), call/cc (создание и переход на продолжение), delay
, force
, null?
(и другие встроенные предикаты), if
, cond
.
Встроенные функции могут иметь разную сложность!
Например,
(map f xs)
—O(len(xs)×T(f))
, гдеT(f)
— среднее время работы(f x)
.(length xs)
—O(len(xs))
.(append xs ys)
—O(len(xs))
.
.
(define (append xs ys) (if (null? xs) ys (cons (car xs) (append (cdr xs) ys))))
(define (f x) (lambda (y) (+ x y)) (define f1 (f 1)) (define f7 (f 7)) (f1 10) → 11 (f7 10) → 17
eqv?
— атомы сравнивает по значению, сложные типы данных (списки, векторы, lambda) — по ссылке.eq?
— может и атомы сравнивать по ссылке.equal?
— сравнивает аргументы по значению.=
— равенство чисел. Может сравнивать числа разных типов.- Функции сравнения отдельных типов вроде
string=?
…
Функция equal?
медленная, т. к. сравнивает аргументы по значению, в частности, для списков
сравнивает их содержимое. Но она наиболее предсказуемая.
Функции eq?
и eqv?
работают быстро, но могут давать неожиданные результаты.
(define x …) (define y x) (eq? x y) → #t (eqv? x y) → #t (equal? x y) → #t
LISP — Списки — CoderLessons.com
Списки были самой важной и основной составной структурой данных в традиционном LISP. На сегодняшний день Common LISP предоставляет другие структуры данных, такие как вектор, хеш-таблица, классы или структуры.
Списки – это отдельные связанные списки. В LISP списки строятся в виде цепочки простой структуры записей с именем cons, связанной вместе.
Минусы Запись Структура
Минусы – это структура записи, содержащая два компонента, которые называются car и cdr.
Минусы ячейки или минусы – это объекты значений пар, которые создаются с помощью функции cons.
Функция cons принимает два аргумента и возвращает новую cons-ячейку, содержащую два значения. Эти значения могут быть ссылками на любой тип объекта.
Если второе значение не равно nil или другой cons-ячейке, то значения печатаются в виде пунктирной пары, заключенной в скобки.
Два значения в ячейке cons называются car и cdr. Функция car используется для доступа к первому значению, а функция cdr – для доступа ко второму значению.
пример
Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.
Live Demo
(write (cons 1 2)) (terpri) (write (cons 'a 'b)) (terpri) (write (cons 1 nil)) (terpri) (write (cons 1 (cons 2 nil))) (terpri) (write (cons 1 (cons 2 (cons 3 nil)))) (terpri) (write (cons 'a (cons 'b (cons 'c nil)))) (terpri) (write ( car (cons 'a (cons 'b (cons 'c nil))))) (terpri) (write ( cdr (cons 'a (cons 'b (cons 'c nil)))))
Когда вы выполняете код, он возвращает следующий результат –
(1 . 2) (A . B) (1) (1 2) (1 2 3) (A B C) A (B C)
Вышеприведенный пример показывает, как структуры cons могут использоваться для создания единого связанного списка, например, список (ABC) состоит из трех cons-ячеек, связанных друг с другом их cdrs .
Схематически это можно выразить как –
Списки в LISP
Хотя cons-ячейки могут использоваться для создания списков, построение списка из вложенных вызовов функции cons не может быть лучшим решением. Функция списка скорее используется для создания списков в LISP.
Функция list может принимать любое количество аргументов и, поскольку она является функцией, она оценивает свои аргументы.
Первая и остальные функции дают первый элемент и остальную часть списка. Следующие примеры демонстрируют концепции.
Пример 1
Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.
Live Demo
(write (list 1 2)) (terpri) (write (list 'a 'b)) (terpri) (write (list 1 nil)) (terpri) (write (list 1 2 3)) (terpri) (write (list 'a 'b 'c)) (terpri) (write (list 3 4 'a (car '(b . c)) (* 4 -2))) (terpri) (write (list (list 'a 'b) (list 'c 'd 'e)))
Когда вы выполняете код, он возвращает следующий результат –
(1 2) (A B) (1 NIL) (1 2 3) (A B C) (3 4 A B -8) ((A B) (C D E))
Пример 2
Создайте новый файл исходного кода с именем main. lisp и введите в него следующий код.
Live Demo
(defun my-library (title author rating availability) (list :title title :author author :rating rating :availabilty availability) ) (write (getf (my-library "Hunger Game" "Collins" 9 t) :title))
"Hunger Game"
Функции управления списком
В следующей таблице приведены некоторые часто используемые функции управления списками.
Sr.No. | Описание функции |
---|---|
1 | автомобиль Он принимает список в качестве аргумента и возвращает свой первый элемент. |
2 | корд Он принимает список в качестве аргумента и возвращает список без первого элемента |
3 | минусы Он принимает два аргумента, элемент и список, и возвращает список с элементом, вставленным на первое место. |
4 | список Он принимает любое количество аргументов и возвращает список с аргументами в качестве элементов-членов списка. |
5 | присоединять Он объединяет два или более списка в один. |
6 | прошлой Он берет список и возвращает список, содержащий последний элемент. |
7 | член Он принимает два аргумента, второй из которых должен быть списком, если первый аргумент является членом второго аргумента, а затем возвращает остаток списка, начинающийся с первого аргумента. |
8 | задний ход Он берет список и возвращает список с верхними элементами в обратном порядке. |
автомобиль
Он принимает список в качестве аргумента и возвращает свой первый элемент.
корд
Он принимает список в качестве аргумента и возвращает список без первого элемента
минусы
Он принимает два аргумента, элемент и список, и возвращает список с элементом, вставленным на первое место.
список
Он принимает любое количество аргументов и возвращает список с аргументами в качестве элементов-членов списка.
присоединять
Он объединяет два или более списка в один.
прошлой
Он берет список и возвращает список, содержащий последний элемент.
член
Он принимает два аргумента, второй из которых должен быть списком, если первый аргумент является членом второго аргумента, а затем возвращает остаток списка, начинающийся с первого аргумента.
задний ход
Он берет список и возвращает список с верхними элементами в обратном порядке.
Обратите внимание, что все функции последовательности применимы к спискам.
Пример 3
Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.
Live Demo
(write (car '(a b c d e f))) (terpri) (write (cdr '(a b c d e f))) (terpri) (write (cons 'a '(b c))) (terpri) (write (list 'a '(b c) '(e f))) (terpri) (write (append '(b c) '(e f) '(p q) '() '(g))) (terpri) (write (last '(a b c d (e f)))) (terpri) (write (reverse '(a b c d (e f))))
Когда вы выполняете код, он возвращает следующий результат –
A (B C D E F) (A B C) (A (B C) (E F)) (B C E F P Q G) ((E F)) ((E F) D C B A)
Конкатенация автомобилей и CDR Функции
Функции car и cdr и их комбинация позволяют извлечь любой конкретный элемент / элемент списка.
Однако последовательности функций car и cdr можно сократить, объединив букву a для car и d для cdr внутри букв c и r.
Например, мы можем написать cadadr для сокращения последовательности вызовов функций – car cdr car cdr.
Таким образом, (cadadr ‘(a (cd) (efg))) вернет d
Пример 4
Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.
Live Demo
(write (cadadr '(a (c d) (e f g)))) (terpri) (write (caar (list (list 'a 'b) 'c))) (terpri) (write (cadr (list (list 1 2) (list 3 4)))) (terpri)
Когда вы выполняете код, он возвращает следующий результат –
списков в LISP — GeeksforGeeks
Улучшить статью
Сохранить статью
- Последнее обновление: 12 окт, 2021
Улучшить статью
Сохранить статью
Списки в обычном LISP — это просто одиночный связанный список. В LISP списки представляют собой цепочки записей. Говоря о структурах записей в LISP, очень важна концепция Cons. Cons в LISP представляет собой структуру записи с двумя основными компонентами. Функция cons принимает 2 аргумента и возвращает новую ячейку cons с car и dir.
- car: Используется для доступа к первому значению в функции cons.
- cdr: Используется для доступа ко второму значению в функции cons.
Примечание: Если второе значение не равно нулю или представляет собой просто другую ячейку cons, то значения печатаются в виде пары точек, заключенных в круглые скобки.
Пример:
Lisp
Вывод: (GEEKSFORG) (999) (А Б) (A B C) Списки в LISP:Функция списка в LISP может использоваться для создания списка в LISP. Синтаксис: запись(список значение1 значение 2 ...) Примечание: Функция списка может принимать любой номер. аргументов. Example: Lisp
Вывод: (1 2) (Г Е Е К С) (ГЕКСФОРГЕКС НИЛЬ) (3 4 GEEKS G 7722) ((GEEKSFORGEEKS IS) (ЛУЧШИЙ РЕСУРС ДЛЯ DSA)) Доступ к элементам списка:Комбинация функций car и cdr в общем LISP может использоваться для извлечения элементов из списка. Комбинация carr и cdr может быть сокращена как cadadr/caar/cadr и так далее. Пример: Lisp
Выход: ЛУЧШИЙ ГИКИ (C D) Статьи по теме Списки | Common LispОсновы Списки можно создавать с помощью функции CL-USER> (список 1 2 3) (1 2 3) Вы можете использовать CL-USER> (первый (список 1 2 3)) 1 CL-USER> (второй (список 1 2 3)) 2 Их также можно использовать для установки элементов: CL-USER> (defparameter my-list (list 1 2 3)) МОЙ СПИСОК CL-USER> (setf (второй мой список) 7) 7 CL-USER> мой список (1 7 3) В более общем случае можно использовать функцию CL-USER> (nth 1 (список 1 2 3)) 2 И работает с CL-USER> (defparameter my-list (список 1 2 3)) МОЙ СПИСОК CL-USER> (setf (nth 1 my-list) 65) 65 CL-USER> мой список (1 65 3) Функции высшего порядкаMap Функция Например: CL-USER> (mapcar #'evenp (список 1 2 3 4 5 6)) (НОЛЬ Т НИЛ Т НОЛЬ Т) Эквивалентно: CL-USER> (list (evenp 1) (evenp 2) (evenp 3) (evenp 4) (evenp 5) (evenp 6)) (НОЛЬ Т НИЛ Т НОЛЬ Т) Другой пример: CL-USER> (mapcar #'string-upcase (list "Hello" "world!")) ("ПРИВЕТ МИР!") Один из способов помочь понять CL-USER> (defun my-map (список функций) (если список (минусы (функция funcall (первый список)) (функция my-map (список остальных))) ноль)) МОЯ КАРТА CL-USER> (my-map #'string-upcase (список "a" "b" "c")) ("А" "Б" "В") Уменьшить Функцию |