作为一个初学者,我在嘴唇上挣扎,在我的程序中,我有一个像这样的列表:
(((NIL (B) (C) (B)) (A)) (E) (G))
但是我要构造的是n维列表(在这种情况下为3-dim):
((B C B)(A)(E G))
我曾尝试将列表变平,但似乎不正确。我将不胜感激。
答案 0 :(得分:4)
由于您并没有真正给出程序要做什么的规范,因此在假定其他某种方式可以使您拥有该结构的情况下,这可以将您拥有的结构变成所需的结构。
您的结构是一个缺点,如果没有其他结构,则其车为null或一个结构。单元素列表的结构列表的cdr,我们需要这些元素。
我将结构称为BLOB-TREE,每个CDR都是BLOB。
(defun blob-to-list (blob)
;; a blob is a list of single-element lists, and we want the elements
(mapcar (lambda (e)
(assert (and (listp e) (null (rest e))))
(first e))
blob))
(defun blob-tree-to-list (blobs)
;; BLOB-TREE is some horrible tree: what we need to do is split it into
;; its car & cdr, and then convert the cdr to a list with
;; blob-to-list, then recurse on the car, until we get a null car.
(labels ((extract-blobs (remains accum)
(etypecase remains
(null accum)
(cons
(extract-blobs (car remains) (cons (blob-to-list (cdr remains))
accum))))))
(extract-blobs blobs '())))
现在
> (blob-tree-to-list '(((NIL (B) (C) (B)) (A)) (E) (G)))
((b c b) (a) (e g))
我相当怀疑这实际上是您想要做的。
作为检查,我编写了一个函数,该函数以所需的形式获取列表并将其转换为Blob树。您可以使用它来检查事物是否正确往返。
(defun list-to-blob-tree (l)
(labels ((list-to-blob (es)
(mapcar #'list es))
(build-blob-tree (tail accum)
(if (null tail)
accum
(build-blob-tree (rest tail)
(cons accum (list-to-blob (first tail)))))))
(build-blob-tree l '())))
如果您真的想处理这样的事情(在现实生活中有时必须这样做),一个好的方法是编写一堆访问器函数,这些函数使您抽象化过时的老式数据结构给定的。
在这种情况下,我们可以编写函数来处理blob:
;;; Blobs are lists are lists where each element is wrapped in a
;;; single-element list
(defun blob->element-list (blob)
;; a blob is a list of single-element lists, and we want the elements
(mapcar (lambda (e)
(assert (and (listp e) (null (rest e))))
(first e))
blob))
(defun element-list->blob (list)
;; turn a list into a blob
(mapcar #'list list))
还有另一组用于处理Blob树的函数,事实证明,这些函数只是交换了汽车和cdrs而构建的列表:
;;; Blob trees are lists, built backwards
;;;
(deftype blob-tree ()
'(or cons null))
(defconstant null-blob-tree nil)
(defun blob-tree-car (blob-tree)
(cdr blob-tree))
(defun blob-tree-cdr (blob-tree)
(car blob-tree))
(defun blob-tree-cons (car cdr)
(cons cdr car))
(defun blob-tree-null-p (blob-tree)
(null blob-tree))
在两种情况下,我只编写了所需的功能:例如有读者,但没有作家。
现在我们可以根据以下抽象编写所需的功能:
(defun blob-tree->element-list (blob-tree)
(labels ((extract-blobs (tree accum)
(assert (typep tree 'blob-tree))
(if (blob-tree-null-p tree)
accum
(extract-blobs (blob-tree-cdr tree)
(cons (blob->element-list (blob-tree-car tree))
accum)))))
(extract-blobs blob-tree '())))
(defun element-list->blob-tree (el)
(labels ((build-blob-tree (elt accum)
(if (null elt)
accum
(build-blob-tree (rest elt)
(blob-tree-cons
(element-list->blob (first elt))
accum)))))
(build-blob-tree el null-blob-tree)))
这意味着,如果表示形式发生变化,这两个轻微的毛发功能也不会改变。
答案 1 :(得分:0)
这对我有用:
(defun peculiar-transform (input-list)
(destructuring-bind (((ignore (xb) (xc) (xb)) (xa)) (xe) (xg)) input-list
`((,xb ,xc ,xb) (,xa) (,xe ,xg))))
测试:
[1]> (peculiar-transform '(((NIL (B) (C) (B)) (A)) (E) (G)))
((B C B) (A) (E G))
[2]> (peculiar-transform '(((NIL (2) (3) (2)) (1)) (5) (7)))
((2 3 2) (1) (5 7))
我已将您的变量重命名为XA
,XB
,...只是为了减少我们在使用A
,B
时出现的混乱。输入测试用例。
在这里,我们利用destructuring-bind
的优势(直接将变量重命名)直接使用您的输入模式作为如何提取元素的规范,然后我们使用反引号语法生成具有以下内容的模板:所需的输出形状,并将提取的片段插入正确的位置。