【问题标题】:Problems with Nth in common lispCommon lisp 中的 Nth 问题
【发布时间】:2011-09-09 03:36:11
【问题描述】:

我正在尝试编写一个可以计算 GPA 的函数。现在我可以进行有限的计算(只有 3 个),但我坚持如何计算更多,而不使用循环或递归(这是主题的要求)如何扩展第 n 个函数?比如:(nth n),如果是这样,这是否意味着我需要编写一个 lambda 表达式?作为一个新手,我可能无法清楚地描述这个问题,真的需要一些帮助..

Glist 是成绩点 Clist 是学分。

GPA=(gradepoint *credithour +gradepoint *credithour) / (credithour之和) 比如:(3*1+3*2+4*1)/(1+2+1 )

这是我的代码:

(defun gpa (Glist Clist)
     (format t "~3,2f~%" 
      (/ 
        (+(nth 0 (mapcar #' * Glist Clist))
          (nth 1 (mapcar #' * Glist Clist))
          (nth 2 (mapcar #' * Glist Clist)))
        (+ (nth 0 Clist)
           (nth 1 Clist)
           (nth 2 Clist))
                   );end "/"
                   );end "format" 
       (values)    );end 

【问题讨论】:

  • 使用标准缩进,不要重复代码来注释括号(我的意思是,这到底是什么?)。例如:gigamonkeys.com/book/…

标签: lisp common-lisp clisp


【解决方案1】:

编辑

这似乎是一个很好的机会来强调一些常见的(小 c)Lisp 想法,所以我充实了我的答案来说明。


正如另一个答案中提到的,您可以使用对列表(数字)进行操作的sum 函数:

(defun sum (nums)
  (reduce #'+ nums))

点积是两个(等长)向量的乘积:

(defun dot-product (x y)
  (sum (mapcar #'* x y)))

函数gpa是两者的简单组合:

(defun gpa (grades credits)
  (/ (dot-product grades credits) (sum credits)))

问题中的示例得到了我们期望的答案(减去被格式化为浮点数):

(gpa '(3 3 4) '(1 2 1))
> 13/4

这个例子有几点值得一提:

  1. 您应该了解mapreduce 及其变体和亲属。这些函数对 Lisp 非常重要,对于列表操作非常有用。 map* 函数通常将序列映射到序列,reduce 通常将序列转换为单个值(但是您可以使用 (reduce #'cons '(1 2 3)) 之类的形式)。

  2. 这是“自下而上”编程方法的一个很好的例子;通过编写像sum 这样经常有用的简单函数,您可以轻松地在其上编写dot-product。现在gpa 函数是一个简单易读的函数,建立在其他两个函数之上。这些都是单行的,对于任何具有 CL 基本知识的人来说都很容易阅读。这与通常应用于 OOP 的方法形成对比。

  3. 没有重复代码。当然,sum 被多次使用,但仅限于有意义的地方。您可以做更多的事情来抽象列表元素总和的概念。在 Scheme 中用函数编写函数更自然,这是一个完全不同的话题。这是一个简单的例子,但没有两个函数在做同样的事情。

【讨论】:

  • 哦,这真的很简单。为什么我没有找到这个功能..无论如何,谢谢你的帮助。我必须更仔细地阅读..
  • +1 “自下而上”的方法解释非常好。我写了一个类似的答案,尽管不那么雄辩;-),最近对于 Scheme:stackoverflow.com/questions/7313563/… 是的,结论是reduce(或 Scheme 中的fold)是一个非常重要的操作。 :-D
  • 啊,我不认为我知道如何在 CL 中执行 foldr ...通过我自己的链接我想通了,这是我想在上面使用的示例: (reduce #'cons <list> :initial-value '() :from-end t) ==> <list>。 [This](en.wikipedia.org/wiki/Fold_(higher-order_function) 巧妙地展示了这是如何在列表中使用标识函数,它只是在 CL 中有笨拙的语法。
  • @Chris 感谢该链接,我不经常使用 Lisps,它很有启发性。
【解决方案2】:

如果您使用nth 遍历列表,那么您做错了。在这种情况下,您可能需要编写一个求和函数:

(defun sum (items)
  (reduce #'+ items))

【讨论】:

  • @Rainer:谢谢!更新。 (我实际上是一个 Schemer,所以我有时不知道在 CL 中做事的“更好的方法”。虽然,在 Scheme 中我也会使用 reduce(虽然它与 CL 版本有不同的参数),所以。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-10
  • 2022-01-15
  • 1970-01-01
  • 2021-02-15
  • 2016-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多