Итерация списка Lisp - PullRequest
       10

Итерация списка Lisp

4 голосов
/ 05 сентября 2008

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

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

Ответы [ 6 ]

5 голосов
/ 05 сентября 2008

Я думаю, что эта строка не права:

(setf xst (remove elem xs))))

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

Возможно, вам будет проще сделать это:

(defun biggerElems (x xs)
  (remove-if (lambda (item) (> item x)) xs))
4 голосов
/ 16 сентября 2008

Краткий AFAIK:

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

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

(< y x)

или используя знаменитый LOOP:

(defun bigger-elements-2 (x xs) 
  (loop for e in xs
        unless (< e x)
        collect e))
1 голос
/ 23 сентября 2008

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

т.е.: 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 в (copy-list xs), а затем использовать удаление вместо удаления (удаление разрушительно ... в зависимости от вашей реализации, это может быть быстрее, чем удалить. Так как вы вызываете это несколько время от времени вы можете получить лучшую производительность, копируя список один раз и уничтожая его).

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

(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, но ваш код выглядит так, как будто он пытается удалить все элементы x больше чем. Решения, которые я написал, возвращают все элементы больше чем x (то есть: удаляют все элементы x больше чем).

1 голос
/ 05 сентября 2008

Если вы хотите сделать это по Лисп-путю, вы можете использовать рекурсию для возврата нового списка:

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

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

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

1 голос
/ 05 сентября 2008

Это сработало так:

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

Зачем было «#»? Это не компилируется с ним.

0 голосов
/ 05 сентября 2008

Зачем было «#»? Это не скомпилировать с ним.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...