Pergunta

Eu tenho uma função que obtém x(um valor) e xs(uma lista) e remove todos os valores maiores que x da lista.Bem, não funciona, você pode me dizer por quê?

(defun biggerElems(x xs) 
  (let ((xst))
    (dolist (elem xs)
      (if (> x elem)
          (setf xst (remove elem xs))))
    xst))
Foi útil?

Solução

Acho que é esta linha que não está certa:

(setf xst (remove elem xs))))

O primeiro argumento a setf é o local, seguido do valor.Parece que você está ao contrário (e xst é também nil ou não inicializado).

Você pode achar mais fácil fazer isso:

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

Outras dicas

AFAIK mais conciso:

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

retornando uma nova lista, ele remove todos os elementos y de xs para os quais

(< y x)

ou usando o famoso LOOP:

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

Funcionou assim:

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

Para que servia o '#'?Não foi compilado com ele.

Se você quiser fazer isso do jeito Lisp, você pode usar recursão para retornar a nova lista:

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

@Luís Oliveira

Esta solução deve contrastar com a postada na pergunta.Se precisássemos fazer algo um pouco mais complicado, seria importante nos basearmos na abordagem recursiva para manipular listas.

@Ben:Não é a chamada setf que está errada - o problema é que ele não está atualizando xs.

ou seja:xst está sendo definido como xs com o elemento removido, mas xs não está sendo atualizado.Se um segundo elemento for removido, xst terá o primeiro de volta.

você precisaria vincular xst a xs e substituir xs na chamada remove por xst.Isso removeria todos os elementos que x é maior que.ou seja:

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

Pode ser um pouco mais rápido definir xst como (lista de cópias xs) e depois usar delete em vez de remover (excluir é destrutivo...dependendo da sua implementação, pode ser mais rápido que remover.Como você está chamando isso várias vezes, poderá obter melhor desempenho copiando a lista uma vez e excluindo-a destrutivamente).

Alternativamente:

(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))

Olhando para trás em sua postagem original, é um pouco confuso ...você diz que remove todos os elementos maiores que x, mas seu código parece estar tentando remover todos os elementos que x é maior.As soluções que escrevi retornam todos os elementos maiores que x (ou seja:remova todos os elementos que x é maior que).

Para que servia o '#'?Não compilou com ele.

Erro de digitação.Normalmente você se refere a funções com #' (como (remove-if #'oddp list)), mas quando estava editando, esqueci de remover o '#'.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top