【问题标题】:Counting occurrence of a word in LISP lists计算 LISP 列表中单词的出现次数
【发布时间】:2019-10-30 07:23:27
【问题描述】:

所以我必须在 lisp 的列表中计算一个单词(或字符,更具体地说)的出现次数。例如输入:

(freq  'c '(a c c c c (c c c e)))

应该产生 7 个计数,因为 list 参数中有 7 个 c。我拥有的代码如下,但它不起作用。我可以计算作为基本元素的 4 个 c 和子列表中的 3 个 c,但我不知道如何将它们加在一起。另外,我只使用原始数据类型。

(defun freq (a L)
    (cond
        ((null L) 0)
        ((listp (car L)) ( (freq a (car L))) ((freq a (cdr L))))
        ((eq a (car L))(+ 1 (freq a (cdr L))))
        (t ((freq a (cdr L))))))

【问题讨论】:

  • 在你的第二个cond 条件下,不应该添加那些递归调用
  • 如何添加递归调用?很抱歉这个基本问题,但我在这里几乎是从头开始自学......就像,我没有分配任何变量,那么我将如何编写这种加法的数学表达式?
  • 只是(+ <call1> <call2>)
  • 所以我会设置第二个条件条件(因为我的原始代码中只有一个条件)并执行 (+ ) 命令?
  • 不,我指的是cond 中的第二个条件分支——((listp (car L)) (+ (freq ..) (freq ...)))

标签: recursion lisp common-lisp


【解决方案1】:

如果它是一个字符,那么它应该使用这个前缀 -> #\ 并且序列将是一个字符串,因此这里不需要递归。

(count #\c "(a c c c c (c c c e))") => 7

您在示例中处理的是通过包含其他符号或缺点的列表的符号(带单引号)。因此,如果您需要计算所有相同的符号,您可以编写类似的内容:

(defparameter *nb* 0)

(defun look-deeper (test seq)
    (loop for i in seq do
          (compare test i)))

(defun compare (test item)
  (let ((type (type-of item)))
    (case type
      (symbol (when (eql test item) (incf *nb*)))
      (cons   (look-deeper test item)))))

(look-deeper 'c '(a c c c c (c c c e))) => NIL
*nb* => 7

或者更好的..

【讨论】:

    【解决方案2】:
     (defun count-occurences (obj lst)
       (let ((acc 0))
       (labels ((test (obj-2)
              (eq obj obj-2)))
         (dolist (x lst)
           (if (consp x)
           (let ((sample (remove-if-not #'test x)))
             (if sample
             (incf acc (length sample))))
           (if (eq x obj)
               (incf acc 1)))))
       acc))
    

    我们可以创建一个函数,该函数接受一个要测试的 obj 和一个 lst 作为参数,并创建一个本地累加器来跟踪 obj 在列表中出现的次数。然后我们可以创建一个本地函数来测试我们传递给它的 obj 是否与作为参数传递给全局函数的 obj 相等(另请注意,如果您正在使用字符串,您可能希望使用 string-equal 或相等,因为 eq 将不起作用,因为它们不是同一个对象,但 eq 将与您在示例中使用的符号一起使用)。然后我们可以遍历列表,如果列表中的元素是 cons,我们可以使用 remove-if-not 删除任何未通过我们测试的元素(不是 obj 的 eq),并基于列表的长度相应地增加我们的累加器。如果它不是 cons 并且是我们的 obj 的 eq,我们还将递增累加器,然后我们可以返回累加器的值。

    如果我们对其进行测试:

    CL-USER> (count-occurences 'c '(a c c c c (c c c)))
    7
    

    【讨论】:

      【解决方案3】:

      您的逻辑实际上是正确的,只是代码中存在一些小括号错误问题。您的代码工作所需的唯一更改是更改您的 listpt 子句

      ((listp (car L)) ( (freq a (car L))) ((freq a (cdr L))))
      

      进入

      ((listp (car L)) (+ (freq a (car L)) (freq a (cdr L))))
      

       (t ((freq a (cdr L))))
      

      进入

      (t (freq a (cdr L)))
      

      然后评估你的函数就像你期望的那样工作:

       (defun freq (a L)
          (cond
              ((null L) 0)
              ((listp (car L)) (+ (freq a (car L)) (freq a (cdr L))))
              ((eq a (car L))(+ 1 (freq a (cdr L))))
              (t (freq a (cdr L)))))
      
      
      (freq  'c '((a (c f c)) c c c (c c (d c f (c 8 c) c) e))) ; => 11 (4 bits, #xB, #o13, #b1011)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-25
        • 2021-02-05
        • 1970-01-01
        • 2021-10-15
        • 2011-08-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多