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))
最も簡潔なAFAIK:
(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))
これをLispWayで実行したい場合は、再帰を使用して新しいリストを返すことができます。
(defun biggerElems (x xs)
(cond ((null xs) NIL)
((< x (car xs))
(biggerElems x (cdr xs)))
(t
(cons (car xs) (biggerElems x (cdr xs))))))
@ルイス・オリヴェイラ
この解決策は、質問に投稿されたものと対比することです。もう少し複雑なことをする必要がある場合は、リストを操作するための再帰的なアプローチに基づいていることが重要です。
それは次のように機能しました:
(defun filterBig (x xs)
(remove-if (lambda (item) (> item x)) xs))
「#」は何のためのものですか? それはそれでコンパイルされませんでした。
@Ben: 間違っているのは 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) に設定してから、remove の代わりに delete を使用する方が少し速いかもしれません (delete は破壊的です...実装によっては、remove よりも速い場合があります。これを複数回呼び出しているため、リストを一度コピーして破壊的に削除すると、パフォーマンスが向上する場合があります)。
または:
(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)
)で関数を参照しますが、編集中に「#」を削除するのを忘れました。