Общая функция Lisp для определения длины вложенных списков в списке - PullRequest
0 голосов
/ 28 марта 2020

Мне разрешено использовать только конструкцию do, концепцию которой я до сих пор не могу получить гр asp. Я попробовал следующий код, но он возвращает nil.

(defun fun(list)
(do ((i 0 (+ i 1)) (l '() (if (listp (nth i list)) (append l (list (length (nth i list)))))))
((null (nth i list)) l)
)
)

Неправильно ли обновлено значение l? Выход для этого списка (a (b) (c d)) должен быть (1 2).

Ответы [ 2 ]

1 голос
/ 28 марта 2020

Попробуйте мыслить в терминах списков, а не массивов. Вы используете n-й элемент списка, как если бы он был массивом. Вместо этого с помощью do вы можете просматривать список, каждый раз беря следующий подсписок, то есть отбрасывая первый элемент и получая другой список без этого первого элемента.

(defun fun(list)
  (do ((l list (cdr l))
       (result nil) )
      ((null l) (nreverse result))
    (if (listp (car l))
      (push (length (car l)) result) )))

Оператор do принимает три аргумента : список переменных, конечное условие и тело l oop. Первая включает в себя имя переменных, их начальное значение и (необязательно), как они меняются с одной l oop на следующую. Например, (l list (cdr l)) говорит, что вы используете переменную l, начальным значением которой является список ввода, и от одного l oop к следующему он станет CDR самого себя, то есть потеряет свой первый элемент. Конечное условие включает в себя также возвращаемое значение функции. С ((null l) (nreverse result)) мы говорим, что когда переменная l равна нулю, функция завершится и вернет значение (nreverse result). Почему неверс? Потому что мы используем pu sh в теле, которое накапливает значения в неправильном порядке. Наконец, тело говорит функции добавить к result длину первого элемента l всякий раз, когда это список.

0 голосов
/ 29 марта 2020

Перебрать все элементы в nested-list. Для каждого списка в соответствии с listp рассчитайте длину и соберите ее. Список собранных длин является результирующим значением:

(loop for item in nested-list
      if (listp item) collect (length item))

Передайте каждый элемент nested-list в функцию. Для каждого элемента, который является списком, функция возвращает одноэлементный список длины, в противном случае она возвращает пустой список. Списки объединяются в один список и возвращаются.

(mapcan (lambda (x) (if (listp x) (list (length x)))) nested-list)

Удалите элементы, не входящие в список, из nested-list, создав новый список, в котором есть только списки. Затем сопоставьте этот список с помощью функции length, в результате получится список длин:

(mapcar #'length (remove-if-not #'listp nested-list))
...