【问题标题】:Common Lisp: convert between lists and arraysCommon Lisp:在列表和数组之间转换
【发布时间】:2012-03-03 20:24:18
【问题描述】:

我们如何优雅地在任意嵌套的列表和数组之间进行转换?

例如

((1 2 3) (4 5 6))

变成

#2A((1 2 3) (4 5 6))

反之亦然

【问题讨论】:

    标签: arrays list common-lisp


    【解决方案1】:

    二维数组列表:

    (defun list-to-2d-array (list)
      (make-array (list (length list)
                        (length (first list)))
                  :initial-contents list))
    

    要列出的二维数组:

    (defun 2d-array-to-list (array)
      (loop for i below (array-dimension array 0)
            collect (loop for j below (array-dimension array 1)
                          collect (aref array i j))))
    

    list 到 2d 的多维形式很简单。

    (defun list-dimensions (list depth)
      (loop repeat depth
            collect (length list)
            do (setf list (car list))))
    
    (defun list-to-array (list depth)
      (make-array (list-dimensions list depth)
                  :initial-contents list))
    

    要列出的数组更复杂。

    可能是这样的:

    (defun array-to-list (array)
      (let* ((dimensions (array-dimensions array))
             (depth      (1- (length dimensions)))
             (indices    (make-list (1+ depth) :initial-element 0)))
        (labels ((recurse (n)
                   (loop for j below (nth n dimensions)
                         do (setf (nth n indices) j)
                         collect (if (= n depth)
                                     (apply #'aref array indices)
                                   (recurse (1+ n))))))
          (recurse 0))))
    

    【讨论】:

    • @mck: 指定你想要多少层,并为 MAKE-ARRAY 提供正确的维度列表。
    • 需要为 3d 数组编写单独的函数?
    【解决方案2】:

    另一个二维数组列出解决方案:

    (defun 2d-array-to-list (array)
      (map 'list #'identity array))
    

    并列出到二维数组(但可能不如上次回复的解决方案效率高):

    (defun list-to-2d-array (list)
      (map 'array #'identity list))
    

    【讨论】:

    • 嗯...这似乎对我不起作用;在运行 SBCL 1.4.5 的机器上,如果我加载上述定义,然后尝试 (2d-array-to-list #2A((1 2) (3 4))),我得到:The value #2A((1 2) (3 4)) is not of type VECTOR。同样,如果我尝试(list-to-2d-array '((1 2) (3 4))),我会得到ARRAY is a bad type specifier for sequences. 所以......我做错了什么吗?这只适用于一些常见的 lisp 实现吗?这是来自其他 lisp 的吗?其他?
    • MAP 结果类型必须是 LIST 或 VECTOR 的子类型,而不是 ARRAY。这就是为什么您的 LIST-TO-2D-ARRAY 不起作用的原因。 lispworks.com/documentation/HyperSpec/Body/f_map.htm
    【解决方案3】:

    使用强制:将对象强制为 Output-Type-Spec 类型的对象。

    (coerce '(1 2 3) 'vector) => #(1 2 3)
    (coerce #(1 2 3) 'list)   => '(1 2 3)
    

    【讨论】:

    • 这仅适用于一维列表或向量,不适用于一维以上的数组(参见原始问题)。
    猜你喜欢
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 2010-09-15
    • 2014-11-28
    相关资源
    最近更新 更多