是否有一种简单的方法来确定列表是否实际上是一个列表?
我的第一次尝试:
(defun alistp (list)
(and (listp list)
(every (lambda (c)
(and (consp c)
(or (atom (cdr c))
(null (cddr c))))))
list)))
返回(alistp '((1 . 2) (2 . 3)))
但是(alistp '((1 . (4 5 6))))
有解决方案吗?
答案 0 :(得分:5)
好吧,让我们看一下definition关联列表:
协会名单代表一个关联的一个conses列表 带有值的键,每个缺点的汽车是键,而cdr是 与该键相关联的值。
鉴于此,这将是alistp
:
(defun alistp (alist)
(and (listp alist) ; a list
(every #'consp alist))) ; of conses
现在,从你的代码示例中我可以看出你可能已经能够自己实现这个,但是你似乎对alist有不同的定义。我假设你看到的alists的例子看起来或多或少都像这样:((a . x) (b . y))
,也许是((a . x) (b . (y z)))
但是列表作为最后一个元素的虚线列表只是 - 一个列表,并且来自你的示例输入很明显,您希望允许列表作为值。 (无论如何,你为什么不呢?)
我想,您必须意识到,您的示例输入((1 . (4 5 6)))
与((1 4 5 6))
完全相同,这就是我主要看到列表为alist的方式他们在代码中使用的值 - 至少,这是我通常写它们的方式。
现在,您似乎也希望排除nil
值,尽管它们也是列表 - 只是空的()
。所以,你实际想到的定义是这样的:
协会名单表示关联的cons单元列表 具有非零值的键,其中每个缺点的汽车是键,而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
或类似的东西。我建议坚持使用上面的简单版本。