【问题标题】:How to make pairs using nested loop in Lisp如何在 Lisp 中使用嵌套循环进行配对
【发布时间】:2016-10-11 07:35:10
【问题描述】:

我正在尝试在 Lisp 中创建对函数。 pair 函数获取两个输入,然后相互配对并生成一个列表。这是我的代码:

(defun npair (s1 s2)
  (let ((result '()))
    (cond ((null s1) s2)
          ((null s2) s1)
          (t (loop
               (when (null s1) (return result))
               (while (not (null s2))
                 (setq result (cons (list (car s1) (car s2)) result))
                 (setq s2 (cdr s2)))
               (setq s1 (cdr s1)))))))

这个函数应该返回像(npair '(a b c) '(1 2)) -> ((a 1) (a 2) (b 1) (b 2) (c 1) (c 2))

但我的结果只有((a 1) (a 2))。 请帮忙!

【问题讨论】:

  • 当未知时,您的代码无法运行。
  • 您的null case 条件意味着这不是一个正确的笛卡尔积。如果任一列表为空,则结果必须为空:因为非空列表的每个元素与空列表的每个元素的组合都是空的。当然,我们可以随心所欲地定义一个函数;如果它无偿地输出 ad hoc 特殊情况,那么它就不太可能具有有用的价值。

标签: loops while-loop lisp


【解决方案1】:

如果您想在外部循环中累积来自内部循环的值,您最好简单地累积值而不是尝试通过改变变量来实现:

(loop for e1 in p1
   append (loop for e2 in p2
             collect (list e1 e2)))

您的格式也有问题,习惯是不要将终止括号放在新行上。

使用上面的循环构造,您的整个函数将是:

(defun npair (p1 p2)
   (loop for e1 in p1
      append (loop for e2 in p2
                collect (list e1 e2))))

不错,简单易读。

【讨论】:

    【解决方案2】:

    虽然其他人已经向您展示了比您的实现更好的替代方案来实现您想要的结果,但这就是您的实现不起作用的原因:您将s2 的值更改为null,同时结合第一个元素s1s2 的元素,在处理s1 的剩余元素之前,永远不要恢复s2 的原始值。 (这是为什么你应该循环输入值而不首先改变它们的多个很好的理由之一。)

    这是您的实现的一个版本,因为它不会改变其输入,所以它实际上可以工作:

    (defun npair (s1 s2)
      (let ((result '()))
        (cond ((null s1) s2)
              ((null s2) s1)
              (t (loop for e1 in s1
                    do (loop for e2 in s2
                          do (push (list e1 e2) result)))
                 (nreverse result)))))
    

    【讨论】:

      【解决方案3】:

      从外观上看,您希望的结果称为笛卡尔积

      我在 Scheme 编程语言中使用的一个实现是这样的:

      (define (product . args)                                                             
         (if (null? args)                                                                   
             (list '())                                                                     
             (apply append                                                                  
                    (map (lambda (rest)                                                    
                          (map (lambda (first)                                             
                                  (cons first rest))                                       
                                (car args)))                                               
                        (apply product (cdr args))))))
      

      例如这里是使用 Chez Scheme 的输出:

      > (product '(a b c) '(1 2))
       ((a 1) (b 1) (c 1) (a 2) (b 2) (c 2)) 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-10
        • 1970-01-01
        相关资源
        最近更新 更多