我正在尝试编写一个奇怪的函数,所以请耐心等待。这个函数应该有一个列表L
作为参数并有一个sum
多变的。如果L
不是列表,它应该返回nil
。否则,它应该迭代列表的每个元素并执行以下操作:
- 如果元素是数字且小于零,则应从总和中减去 1。
- 如果元素是数字且大于零,则应在总和中加 1。
- 如果元素为 0 或者不是数字,则应在总和中添加 0。
这是我的代码,但无论传入的参数如何,它都会返回 0:
(defun sigsum (L)
(let ((sum 0)) ;;variable sum
(if (not (listp L)) ;;if L is not a list
nil ;;return nil
(dotimes (i (length L)) ;;otherwise loop through L
(if (numberp (elt L i)) ;;if each element is a number
(if (< (elt L i) 0) ;;if is less than 0 subtract 1 from sum
(- sum 1)
(if (> (elt L i) 0) ;;if greater than 0 add 1 to sum
(+ sum 1))
(+ sum 0)) ;;else add 0 to sum
(+ sum 0))) ;;not a number so add 0 to sum
)
sum) ;;return sum
)
一如既往,我们非常感谢任何帮助。
其他答案已经描述了代码中的问题,但查看解决问题的其他方法可能会有所帮助。这是一个非常典型的案例减少 with a 按键功能 (see reduce http://www.lispworks.com/documentation/HyperSpec/Body/f_reduce.htm)。您可以总结以下元素list with (减少'+列表)。但是,您不想只对元素求和,其中一些元素可能不是数字,您希望将每个元素映射到数字(-1、0 或 1),然后将它们相加。这意味着您需要一个关键功能。首先,我们定义一个将元素设为 -1、0 或 1 的函数:
(defun to-number (x)
(cond
((and (numberp x) (< x 0)) -1)
((and (numberp x) (> x 0)) 1)
((or (not (numberp x)) (zerop x)) 0)))
那么你的sum函数需要返回nil如果它的参数不是列表,或者(将 '+ … :key ' 减少为数字)如果它的参数是一个列表:
(defun sum (thing)
(if (not (listp thing))
nil
(reduce '+ thing :key 'to-number)))
从概念上讲,这种方法与applying结果的加法运算符(mapcar '收件人号码列表), but reduce通常是首选,因为调用函数时可以使用最大数量的参数,因此(应用'+(mapcar ...))中断如果(地图车……)返回一个比该列表更长的列表。另一个问题是mapcar将分配一个全新的列表来保存中间值(结果至号码),这是不必要的空间使用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)