【问题标题】:Transposing lists in Common Lisp在 Common Lisp 中转置列表
【发布时间】:2011-03-31 14:22:41
【问题描述】:

我正在尝试转置列表列表;我的 cmets 表明了思考的过程。

(setq thingie  '((1 2 3) (4 5 6) (7 8 9)))  ;;test case

(defun trans (mat)
  (if (car mat)
    (let ((top (mapcar 'car  mat))   ;;slice the first row off as a list
          (bottom (mapcar 'cdr mat))) ;;take the rest of the rows
      (cons top (trans bottom))))    ;;cons the first-row-list with the next-row-list
   mat)

(trans thingie)
=> ((1 2 3) (4 5 6) (7 8 9))           ;;wait what? 

但是,我真的希望它是

((1 4 7) (2 5 8) (3 6 9))

我做错了什么?

【问题讨论】:

  • 这叫matrix transpose
  • @sds: ... yuuup。为什么我三年前没有看到这一点超出了我的范围。给我几分钟,我会解决这个问题。

标签: lisp common-lisp


【解决方案1】:

有一个简单的方法:

(defun rotate (list-of-lists)
  (apply #'mapcar #'list list-of-lists))

您的尝试总是返回原始的mat。修正你的缩进,你会看到if 表单的返回值总是被丢弃。

编辑:这是如何工作的:

  • List 接受任意数量的参数并列出它。它的函数定义可以想象成这样:

    (defun list (&rest arguments)
      arguments) ; exploit the automatic &rest construction
    
  • Mapcar 接受一个函数和任意数量的列表,然后生成一个 通过始终使用调用函数创建的值的新列表 这些列表中的一个元素。示例:(mapcar #'foo '((A B) (C D))) 将构造一个新列表,其中第一个元素是 (foo 'A 'C) 的结果,第二个是(foo 'B 'D) 的结果。

  • Apply 将可扩展参数列表指示符作为其最后一个 争论。这意味着如果你给它一个列表作为它的最后一个 论点,该列表可以“传播”以产生单独的论点 为功能。示例:(apply #'+ '(1 2 3)) 具有相同的 效果为(+ 1 2 3)

现在您可以展开该行了:

(apply #'mapcar #'list '((A B) (C D)))

=>

(mapcar #'list '(A B) '(C D))

=>

(list (list 'A 'C) (list 'B 'D))

=>

'((A C) (B D))

【讨论】:

  • Hnnng。您能否详细说明轮换的原因?我不太明白它是如何生成解决方案的。
  • 有些退化案例有问题。试试(rotate nil)(rotate '(nil))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-16
  • 2014-11-28
  • 2012-10-07
  • 2017-02-23
相关资源
最近更新 更多