2

有没有一种简单的方法来确定列表是否实际上是 alist ?

我的第一次尝试:

(defun alistp (list)
    (and (listp list)
         (every (lambda (c)
                    (and (consp c)
                         (or (atom (cdr c))
                             (null (cddr c))))))
                list)))

返回 T 为(alistp '((1 . 2) (2 . 3)))

但 NIL 为(alistp '((1 . (4 5 6))))

有解决办法吗?

4

1 回答 1

6

好,我们来看看关联列表的定义

关联列表 n. 一个 conses 列表,表示键与值的关联,其中每个 cons 的 car 是键,而 cdr 是与该键关联的值。

鉴于此,这将是一个可能的实现alistp

(defun alistp (alist)
  (and (listp alist)           ; a list
       (every #'consp alist))) ; of conses

现在,从您的代码示例中,我可以看出您可能已经能够自己实现它,但您似乎对 alist 有不同的定义。我假设您所看到的 alist 示例都或多或少看起来像这样:((a . x) (b . y)),也许((a . x) (b . (y z)))但是带有列表作为其最后一个元素的虚线列表只是 - 一个列表,从您的示例输入中可以清楚地看到您想要允许列表作为价值观。(你为什么不呢?)

我想你必须意识到的是,你的示例输入((1 . (4 5 6)))完全相同((1 4 5 6))这就是我在代码中使用列表作为其值的大多数情况下看到的 alist 的方式——至少,我通常是这样编写它们的。

现在,您似乎还想排除nil值,尽管它们也是列表——只是空的()。所以,你真正想到的定义是这样的:

关联列表 n. 一个 cons 单元列表,表示键与非 nil 值的关联,其中每个 cons 的 car 是键,而 cdr 是与该键关联的值。

如果这确实是您想要的,请遵循新定义:

(defun alistp (alist)
  (flet ((true-cdr-p (element)
           (and (consp element)        ; cons cell
                (cdr element))))       ; with non-nil cdr (i.e. value) 
    (and (listp alist)                 ; a list
         (every #'true-cdr-p alist)))) ; of cons cells with non-nil cdr

或类似的东西。不过,我建议坚持使用上面的简单版本。

于 2013-01-17T05:37:06.473 回答