2008-09-05 3 views
4

У меня есть функция, которая получает x (значение) и xs (список) и удаляет все значения, которые больше, чем x из списка. Ну, это не работает, можете ли вы сказать мне, почему?Lisp list iteration

(defun biggerElems(x xs) 
    (let ((xst)) 
    (dolist (elem xs) 
     (if (> x elem) 
      (setf xst (remove elem xs)))) 
    xst)) 

ответ

5

Я думаю, что эта линия, что это не так:

(setf xst (remove elem xs)))) 

Первый аргумент setf это место, за которым следует значение. Похоже, что у вас есть это в обратном направлении (и xst либо nil, либо неинициализирован).

Вы могли бы найти это легче сделать это:

(defun biggerElems (x xs) 
    (remove-if (lambda (item) (> item x)) xs)) 
1

Он работал так:

(defun filterBig (x xs) 
    (remove-if (lambda (item) (> item x)) xs)) 

Что было '#' для? Он не скомпилировался.

0

Для чего «#»? Это не скомпилировать с ним.

Typo. Обычно вы ссылаетесь на функции с #' (например, (remove-if #'oddp list)), но когда я редактировал, я забыл удалить «#».

1

Если вы хотите сделать это лисповский путь, вы могли бы использовать рекурсию, чтобы вернуть новый список:

(defun biggerElems (x xs) 
    (cond ((null xs) NIL) 
     ((< x (car xs)) 
     (biggerElems x (cdr xs))) 
     (t 
     (cons (car xs) (biggerElems x (cdr xs)))))) 

@ Луис Оливейра

Этого решения контрастировать с одной публикуемыми в вопросе , Если бы нам нужно было сделать что-то более сложное, важно, чтобы он был основан на рекурсивном подходе к манипулированию списками.

+0

Просто потому, что вы можете использовать рекурсию в Lisp, не означает, что это «Lisp Way». Есть несколько механизмов для этого в Lisp (как видно здесь в другом месте), и все они идиоматичны. Рекурсивный метод просто самый примитивный. – 2008-09-22 22:43:05

4

Наиболее краткий AFAIK:

(defun bigger-elements (x xs) (remove x xs :test #'<)) 

возвращает свежий список, он удаляет все элементы у из хза, для которых

(< y x) 

или с использованием знаменитой LOOP:

(defun bigger-elements-2 (x xs) 
    (loop for e in xs 
     unless (< e x) 
     collect e)) 
1

@ Бен: Это не звонок setf, это неправильно - проблема в том, что он не обновляет xs.

ie: xst устанавливается в xs с удаленным элементом, но xs не обновляется. Если второй элемент должен быть удален, xst будет первым в нем.

вам нужно привязать xst к xs и заменить xs в вызове remove с помощью xst. Тогда это приведет к удалению всех элементов x больше. то есть:

(defun biggerElems(x xs) 
    (let ((xst xs)) 
    (dolist (elem xs) 
     (when (> x elem) 
     (setf xst (remove elem xst)))) 
    xst)) 

Это может быть немного быстрее, чтобы установить XST в (копирование списка хз), а затем использовать удаление вместо удаления (удалить, разрушительно ... в зависимости от реализации, она может быть быстрее, чем удалить. Поскольку вы вызываете это несколько раз, вы можете получить лучшую производительность, скопировав список один раз и разрушительно удалив из него).

В качестве альтернативы:

(defun bigger-elems (x xs) ; I prefer hyphen separated to camelCase... to each his own 
    (loop for elem in xs when (<= x elem) collect elem)) 

Оглядываясь на исходное сообщение, это немного сбивает с толку ... Вы говорите, что вы удалите все элементы больше, чем х, но ваш код выглядит он пытается удалить все элементы x больше, чем. Решения, которые я написал, возвращают все элементы, большие, чем х (т. Е. Удаляют все элементы х больше).