【问题标题】:Differentiate between a list and an atom in common lisp区分普通lisp中的列表和原子
【发布时间】:2010-11-05 00:21:38
【问题描述】:

我正在制作一个基本的 clisp 函数,它只返回列表中的原子数。我遇到的问题是我需要它为列表中的列表中的原子递增,而不是将列表视为列表中的 1 个元素。

我猜真正的问题是如何在代码中区分元素是列表还是原子?如果我能做到这一点,我可以将列表发送到另一个函数以相加并返回它们包含的原子数。

一清二楚? :)

我这里有一个例子:

(defun list_length (a)
  (cond ((null a) 0)
        (t (+ 1 (list_length (cdr a))))))

如果父列表中没有嵌入列表,这将非常有用,例如, '(1 2 3 (4 5) 6) 将返回 5。我需要它包含 4 和 5 而不是列表 (4 5)。

感谢您的帮助。

乔恩


编辑:

(defun list_length (a)
  (cond ((null a) 0)
        ((listp (car a)) (list_length (car a)))
        (t (+ 1 (list_length (cdr a))))))

[18]> (list_length '(1 2 3 (4 5) 6))
1. Trace: (LIST_LENGTH '(1 2 3 (4 5) 6))
2. Trace: (LIST_LENGTH '(2 3 (4 5) 6))
3. Trace: (LIST_LENGTH '(3 (4 5) 6))
4. Trace: (LIST_LENGTH '((4 5) 6))
5. Trace: (LIST_LENGTH '(4 5))
6. Trace: (LIST_LENGTH '(5))
7. Trace: (LIST_LENGTH 'NIL)
7. Trace: LIST_LENGTH ==> 0
6. Trace: LIST_LENGTH ==> 1
5. Trace: LIST_LENGTH ==> 2
4. Trace: LIST_LENGTH ==> 2
3. Trace: LIST_LENGTH ==> 3
2. Trace: LIST_LENGTH ==> 4
1. Trace: LIST_LENGTH ==> 5
5
[19]> (dribble)

【问题讨论】:

  • 太棒了,这正是我想要的。感谢 sepp2k。但是,这导致我另一个问题...这是我的新代码... (defun list_length (a) ( cond (( null a ) 0 ) (( listp ( car a )) ( list_length ( car a ))) (t ( + 1 ( list_length ( cdr a ))))) ) 再次使用我上面的例子。它实际上会看到 (4 5) 是一个列表并进入它并计算这两个原子,但是当它返回时它会忘记大约 6 并返回程序。所以它添加了 1 2 3 4 5 而不是 6。我将在下面粘贴一个跟踪。
  • 那很丑,贴在上面的代码。我在看到您的其余回复之前发布了虽然 sepp 我会尝试添加该行的最后一部分。

标签: algorithm common-lisp clisp


【解决方案1】:

如果foo 是一个列表,(listp foo) 将返回t,否则返回nil

因此,您可以通过将以下情况添加到您的 cond 来使您的 list_length 函数处理嵌套列表:

((listp (car a)) (+ (list_length (car a)) (list_length (cdr a))))

【讨论】:

    【解决方案2】:

    ATOM 是您要求的谓词。

    我建议使用 FLATTEN,这是一种扁平化列表中的列表的标准例程 - 我在这里介绍一种实现。

    (defun flatten (x)
      "descend into the supplied list until an atom is hit.
    append the atom to the flattened rest"
      (if (endp x)
          x
        (if (atom (car x ))
        (append (list (car x)) (flatten (cdr x)))
          (append (flatten (car x)) (flatten (cdr x ))))))
    

    Flatten 返回一个列表:您可以在列表上运行 LENGTH 以查看您最终处理了多少个 ATOMS。

    【讨论】:

    • 这是一个很好的建议,但我可能无法改变原始列表。 :(
    • 您没有更改原始列表,而是返回了一个新列表。
    • 你是对的。 :) 这也有效,这绝对是一种与我原来的方法不同的思考方式。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    • 2015-11-13
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-20
    相关资源
    最近更新 更多