首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >适当使用reduce,嵌套循环

适当使用reduce,嵌套循环
EN

Code Review用户
提问于 2013-03-10 20:09:36
回答 1查看 633关注 0票数 1

下面是Dijkstra最短路径算法的一个实现。它的输入graph表示为源节点到目标节点和弧权重的关联列表。

我的问题是关于以下几个方面:我是否遗漏了一种简化min-path函数的方法?也许伟大而强大的loop可以做reduce的S的工作?

代码语言:javascript
复制
(defun dijkstra (source target graph)
  (labels ((min-path (&optional arc-1 arc-2)
             (let ((price-1 (cdr arc-1))
                   (price-2 (cdr arc-2)))
               (cond 
                 ((and (not (null arc-1)) (not (null arc-2))) (if (< price-1 price-2)
                                                                arc-1 arc-2) )
                 ((and (not (null arc-1)) (null (arc-2))) arc-1) 
                 ((and (not (null arc-2)) (null (arc-1))) arc-2))))
           (get-best-path (visited)
             (reduce #'min-path (loop for pick in visited 
                                      for start = (car pick) 
                                      for cost = (cdr pick) 
                                      append (loop for arc in (cdr (assoc start graph))
                                                   when (null (assoc (car arc) visited))
                                                   collect (cons (car arc) (+ cost (cdr arc))))))))
    (loop named main-loop
          with visited = (list (cons source 0))
          for best-arc = (get-best-path visited)

          when (not (null best-arc)) 
          do (push best-arc visited)  
          until (or (null best-arc)
                  (eql (car best-arc) target)) 
          finally 
          (format t "Found shortest path from ~A to ~A: ~A~%" source target best-arc)
          (return-from main-loop (cdr best-arc)))))

我是Lisp的新手,我希望得到任何建议,尤其是代码中关于Lisp坏习惯和坏Lisp风格的建议,谢谢。

UPD:新版本,有评论应用-没有警告,不像原来的版本。

代码语言:javascript
复制
(defun dijkstra (source target graph)
  (labels ((min-path (&optional arc-1 arc-2)
             (cond ((and arc-1 arc-2) (if (< (cdr arc-1) (cdr arc-2)) arc-1 arc-2))
                   (arc-1 arc-1)
                   (arc-2 arc-2)
                   (t nil)))
           (get-best-path (visited)
             (reduce #'min-path 
                     (loop for pick in visited 
                           for start = (car pick) 
                           for cost = (cdr pick) 
                           append (loop for arc in (cdr (assoc start graph))
                                        unless (assoc (car arc) visited)
                                        collect (cons (car arc) (+ cost (cdr arc))))))))
    (loop with visited = (list (cons source 0))
          for best-arc = (get-best-path visited)
          when best-arc do
          (push best-arc visited)  
          until (or (null best-arc) (eql (car best-arc) target)) 
          finally (return (cdr best-arc)))))
EN

回答 1

Code Review用户

回答已采纳

发布于 2013-03-10 21:16:09

首先,(not (null x))不是非常惯用的;只需使用x

接下来,您没有处理cond中的所有大小写(显然您指的是(null arc-2)而不是(null (arc-2)))。如果是这样的话,我会放弃let,转而使用嵌套的ifs。

最后,回答您最初的问题:当然,loop可以做reduce所能做的一切,但是如果您对后者的意图更明确,那么就使用它吧!

编辑:unlesswhen (null ...)更惯用。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/23701

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档