如何创建n维列表?

时间:2019-01-21 13:08:58

标签: list lisp

作为一个初学者,我在嘴唇上挣扎,在我的程序中,我有一个像这样的列表:
(((NIL (B) (C) (B)) (A)) (E) (G))

但是我要构造的是n维列表(在这种情况下为3-dim):

((B C B)(A)(E G))

我曾尝试将列表变平,但似乎不正确。我将不胜感激。

2 个答案:

答案 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))

我已将您的变量重命名为XAXB,...只是为了减少我们在使用AB时出现的混乱。输入测试用例。

在这里,我们利用destructuring-bind的优势(直接将变量重命名)直接使用您的输入模式作为如何提取元素的规范,然后我们使用反引号语法生成具有以下内容的模板:所需的输出形状,并将提取的片段插入正确的位置。