问题
I need to create a recursive method in LISP that takes the numbers in a list and finds the sum. Anything in the list that is not a number is skipped (For example, if the list contains "Cheese 12 Dog 8 Shoe 5", the output would be 25).
Right now my code finds the sum, but throws an error if there is anything in the list that is not a number. What can be changed to fix that?
(defun adder (lis)
(cond
((null lis) 0)
(t (eval (cons '+ lis)) )
)
)
回答1:
This would do:
(defun adder (lis)
(if (null lis)
0
(let ((c (car lis)))
(if (numberp c)
(+ c (adder (cdr lis)))
(adder (cdr lis))))))
Your version is not recursive (you don't call adder inside of adder), maybe you meant something like this (which is non-recursive)?
(defun adder (lis)
(apply '+ (remove-if-not 'numberp lis)))
回答2:
Using apply
on lists that can be long is a bit dangerous. If the list is longer than call-arguments-limit, then (apply '+ list)
won't work. Now, call-arguments-limit
is typically pretty big in modern Lisps, but it's allowed to be as small as 50. For more information about this, see:
- Common lisp: How many argument can a function take? (this answer uses
(reduce '+ …)
) - In Lisp, how many inputs can the + function actually have?
I think your best bet would be to use reduce '+ list
with a key function that takes each number to itself and each non-number to 0
. (This key function is what abiessu mentioned in a comment.)
(reduce '+ list :key (lambda (x) (if (numberp x) x 0)))
CL-USER> (let ((list '(cheese 12 dog 8 shoe 5)))
(reduce '+ list :key (lambda (x) (if (numberp x) x 0))))
25
CL-USER> (let ((list '()))
(reduce '+ list :key (lambda (x) (if (numberp x) x 0))))
0
Instead of using a more complex key function, you could also use (remove-if-not 'numberp list)
to get rid of the non-numbers (or (remove-if (complement 'numberp) list)
):
CL-USER> (let ((list '(cheese 12 dog 8 shoe 5)))
(reduce '+ (remove-if-not 'numberp list)))
25
CL-USER> (let ((list '()))
(reduce '+ (remove-if-not 'numberp list)))
0
来源:https://stackoverflow.com/questions/19936840/ignore-non-number-values-in-a-list-and-find-the-sum-recursive-method