質問
x(値)とxs(リスト)を取得し、リストからxより大きい値をすべて削除する関数があります。うまくいきません。理由を教えていただけますか?
(defun biggerElems(x xs)
(let ((xst))
(dolist (elem xs)
(if (> x elem)
(setf xst (remove elem xs))))
xst))
解決
正しくないのはこの行だと思います:
(setf xst (remove elem xs))))
最初の引数は setf
場所、その後に値が続きます。どうやら逆に持っているようです(そして xst
どちらかです nil
または初期化されていません)。
これを行う方が簡単かもしれません:
(defun biggerElems (x xs)
(remove-if (lambda (item) (> item x)) xs))
他のヒント
私の知る限り最も簡潔な:
(defun bigger-elements (x xs) (remove x xs :test #'<))
新しいリストを返すと、xs からすべての要素 y が削除されます。
(< y x)
または有名な LOOP を使用します。
(defun bigger-elements-2 (x xs)
(loop for e in xs
unless (< e x)
collect e))
それは次のように機能しました:
(defun filterBig (x xs)
(remove-if (lambda (item) (> item x)) xs))
「#」は何のためにあったのでしょうか?それはコンパイルできませんでした。
これを Lisp 方式で実行したい場合は、再帰を使用して新しいリストを返すことができます。
(defun biggerElems (x xs)
(cond ((null xs) NIL)
((< x (car xs))
(biggerElems x (cdr xs)))
(t
(cons (car xs) (biggerElems x (cdr xs))))))
@ルイス・オリベイラ
この解決策は、質問に投稿された解決策とは対照的です。もう少し複雑なことを行う必要がある場合は、リストを操作するための再帰的アプローチに基づいていることが重要です。
@ベン:間違っているのは setf 呼び出しではありません。問題は xs を更新していないことです。
つまり:xst は要素が削除されて xs に設定されていますが、xs は更新されていません。2 番目の要素が削除される場合、xst は最初の要素を元に戻します。
xst を xs にバインドし、remove 呼び出しの xs を 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) に設定し、削除の代わりに削除を使用する方が若干速いかもしれません (削除は破壊的です...)実装によっては、削除よりも高速な場合があります。これを複数回呼び出すため、リストを 1 回コピーしてそこから破壊的に削除するとパフォーマンスが向上する可能性があります)。
あるいは:
(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 はより大きいです)。
「#」は何のためにあったのでしょうか?コンパイルしませんでした。
打ち間違え。通常、関数を参照するには #'
(のように (remove-if #'oddp list)
)を作成しましたが、編集時に「#」を削除するのを忘れてしまいました。