【问题标题】:Create a partition of list into three parts in scheme在方案中将列表分区创建为三个部分
【发布时间】:2018-09-12 04:12:46
【问题描述】:

我正在尝试找到一种将列表分成三部分的方法。我使用了一个辅助函数,参数应该如下:它评估为三个列表的列表,包含 1)列表中的项目小于枢轴,2)列表中的项目等于枢轴,3)列表中大于枢轴的项目。

(define (partition lst item)
  (define (partition-iter lst less same greater)
   (cond ((null? lst)(list less same greater ))
      ((< (car lst) item)(partition-iter (cdr lst)
                                         (cons (car lst) less)
                                         same
                                         greater ))
      ((= (car lst) item)
       less
       (cons (car lst) same)
       (else
        (partition-iter (cdr lst) (cons (car lst) greater))))))
(partition-iter lst '() '() '()))    

else 子句之前的一切都应该有效,但在那之后我就被卡住了。任何帮助表示赞赏

【问题讨论】:

  • (= ...) 术语和else 术语应该看起来像(&lt; ...) 术语,不同之处在于您使用不同的地方。现在你没有这样做,你的else(= ...) 术语的结果。

标签: list scheme racket partitioning r5rs


【解决方案1】:

这是您的代码,缩进以便相应的项目在视觉上对齐:

(define (partition lst item)
  (define (partition-iter lst less same greater)
   (cond
      ((null? lst)
                      (list less same greater ))

      ((< (car lst) item)
                      (partition-iter (cdr lst)
                                      (cons (car lst) less)
                                      same
                                      greater))
      ((= (car lst) item)
                      less

                      (cons (car lst) same)

                      (else
                                      (partition-iter (cdr lst)
                                                      (cons (car lst) greater))))))
  (partition-iter lst '() '() '()))

我想你可以马上看出它有什么问题,现在。它是不对称的,完全不合常理,即使括号是平衡的。 else 子句 inside 另一个 cond 子句?那是什么??

道德是,不要害怕使用空白来看得更清楚。很多很多的空白。

没有它,Scheme 看起来就像一堵无法穿透的文字墙,无论是括号还是没有括号。以及推荐的缩进样式。做。不是。帮助。

修复很明显,最小且简单:只需以 (??) 开始编写它的相同样式完成代码。处理另外两种情况,构建三个临时列表,同时通过在这三种情况中的每一种情况下重复使用 cdrs 来迭代输入列表:

(define (partition lst item)
  (define (partition-iter lst less same greater)
   (cond
      ((null? lst)
                      (list less same greater ))

      ((< (car lst) item)
                      (partition-iter (cdr lst)
                                      (cons (car lst) less)
                                      same
                                      greater ))
      ((= (car lst) item)
                      (partition-iter (cdr lst)
                                      less
                                      (cons (car lst) same)
                                      greater ))

      (else  ; (> (car lst) item)             ; keep it here for documentation!
                      (partition-iter (cdr lst)
                                      less
                                      same
                                      (cons (car lst) greater) )) ))
  (partition-iter lst '() '() '()))

我现在什至不必将它加载到 DrRacket 中就可以看到它没问题。

对称是美丽的。对称是对的。


顺便说一句,在带有守卫的模式匹配伪代码中,它可以写成

partition lst item = partition-iter lst [] [] []
  where
  partition-iter [] less same greater  =  [less,      same,      greater]
  partition-iter [a, ...lst] less same greater 
     | a < item   =  partition-iter  lst  [a, ...less]   same    greater 
     | a == item  =  partition-iter  lst  less    [a, ...same]   greater
     | else       =  partition-iter  lst  less    same    [a, ...greater]

我认为这在视觉上更加明显。在它和正确的 Scheme 之间来回切换是纯粹的句法转换问题。

【讨论】:

    【解决方案2】:

    当前的辅助函数partition-iter 由于其设计中的一些严重错误而无法工作。但首先,让我提供两个可行的版本:

    第一个(简单)版本,

    #lang racket
    
    ; LoN = List-of-Numbers
    
    ; partition :: LoN Number -> List-of-LoN
    (define (partition1 lst pivot)
      (local([; auxiliary function
              ; part :: LoN LoN LoN LoN -> List-of-LoN
              define (part xs LT EQ GT)
              ; if empty list
              (if (null? xs) (list LT EQ GT)
                  ;else
                  (let* ([head (first xs)]
                         [tail (rest  xs)]
                         [prtd (part tail LT EQ GT)]                    
                         [LT* (first prtd)]
                         [EQ* (second prtd)]
                         [GT* (third prtd)])
                    ;--in--
                    (cond
                      ; if x < pivot, add the element to LT
                      [(< head pivot) (list {cons head LT*} EQ* GT*)]
                      ; if x = pivot, add the element to EQ
                      [(= head pivot) (list LT* {cons head EQ*} GT*)]
                      ; if x > pivot, add the element to GT
                      [else (list LT* EQ* {cons head GT*})]
                      )
                    ) ) ]
             )
        ;--in--
        (part lst null null null)
        )
      )
    

    第二个版本,更接近你的实现,但使用fold

    #lang racket
    
    ; partition :: LoN Number -> List-of-LoN
    (define (partition2 lst pivot)
      (local([; auxiliary function
              ; part :: LoN LoN LoN LoN -> List-of-LoN
              define (part x LT-EQ-GT)
              (local ([define-values (LT* EQ* GT*) (apply values LT-EQ-GT)])
                ;--in--
                (cond
                  ; if x < pivot, add the element to LT
                  [(< x pivot) (list {cons x LT*} EQ* GT*)]
                  ; if x = pivot, add the element to EQ
                  [(= x pivot) (list LT* {cons x EQ*} GT*)]
                  ; if x > pivot, add the element to GT
                  [else (list LT* EQ* {cons x GT*})]
                  )
                ) ]
             )
        ;--in--
        (foldr part '(() () ()) lst)
        )
      )
    

    试试吧,

    (partition2 '(1 2 3 4 4 3 4 5 6) 4) ;; yields '((1 2 3 3) (4 4 4) (5 6)).
    

    请注意,second (fold-) 版本更快(并且 imo 更好)。

    最后,您的实现在以下几行中存在错误(行号从 1 开始):

    -- 第 4-7 行应该是:

    (partition-iter (cdr lst) (cons (car lst) less) same greater)
    

    -- 第 9-10 行应该是:

    (partition-iter (cdr lst) less (cons (car lst) same) greater)
    

    -- 第 12 行应该是:

    (partition-iter (cdr lst) less same (cons (car lst) greater))
    

    最后,在您当前的实现中,您应该在最后一行使用foldlfoldr(或类似的东西)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-12
      • 2016-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多