在更新其中一个列表时循环遍历两个列表

时间:2013-07-15 16:53:52

标签: lisp iteration common-lisp

我有两个列表如下:

(x y z) & (2 1)

我希望得到一个结果:

((x y) (z))

列表的关系非常清楚。所以基本上我想把第一个列表的成员重新排列成一个列表,列表中有两个(第二个列表的长度)列表。 我尝试过两次dotimes迭代来做到这一点:

(let ((result) (list1* list1))
   (dotimes (n (length list2) result)
     (progn (setq result
                  (append result
                          (list (let ((result2))
                                  (dotimes (m (nth n list2) result2)
                                    (setq result2
                                         (append result2
                                                 (list (nth m list1*)))))))))
            (setq list1*
                 (subseq list1* 0 (nth n list2))))))

我的想法是我制作了预期结果的第一个列表(x y),然后我想更新(x y z)列表,以便删除x任何y,我只有(z)。然后循环再次运行以获得预期结果中的(z)列表。这不能正常工作并导致:

 ((x y) (x))

这意味着显然第二个基本更新list1 *的命令是不起作用的。显然,必须有一个正确和更好的方法来做到这一点,我想知道是否有人可以帮助解决这个问题。还解释为什么不能解释解决方案?

2 个答案:

答案 0 :(得分:3)

如果我看到了这一点,那么您的问题就在(subseq list1* 0 (nth n list2)),它会返回您想要的列表部分。

我提供以下内容:

(defun partition-list (list lengths)
  (mapcar (lambda (length)
            (loop :repeat length
                  :collect (pop list)))
          lengths))

当然,这有点过于简单,因为它不处理意外输入,例如(length list)小于(reduce #'+ lengths),但它可以扩展。

答案 1 :(得分:1)

仅为示例,使用iterate

的备选方案
(defun partition-list (list by)
  (iter:iter
    (iter:for element in list)
    (iter:for i from 1)
    (iter:generating measure in by)
    (iter:collect element into sublist)
    (when (= (or measure (iter:next measure)) i)
      (iter:collect sublist)
      (iter:next measure)
      (setf i 0 sublist nil))))