繁体   English   中英

列表中重复元素的计数

[英]Counts of repeated elements in a list

该程序获取元素重复的列表,例如L = (aaabbbcccd) ,并输出项目列表和重复次数,例如((a 3)(b 3)(c 3) d)

(define counter 0)
(define (compress liste)
(if (or (null? liste) (null? (cdr liste)))
   liste
(let ((compressed-cdr (compress (cdr liste)))) 
   (if (equal? (car liste) (car compressed-cdr))
   ((+ counter 1) compressed-cdr)
  ((cons (car liste) counter) (= counter 0) (compressed-cdr))))
                       ))

但是,我收到此错误:

错误:应用程序:不是过程; 期望可以应用于参数的过程
给定:1个参数...

错误是第二个if条件的真实谓词。

对于我来说,很难找出问题出在您的代码中。 我尝试了以下似乎可行的方法。

(define (compress liste)

  (define (helper in prev out)
     (if (null? in)
        (list (list (car out) (length out)))
        (if (equal? prev (car in))
          (helper (cdr in) prev (append out (list (car in))))
          (cons (list (car out) (length out)) (compress in)))))


    (if (null? liste)
      '()
      (helper (cdr liste) (car liste) (list (car liste))))
      )

它使用helper来收集匹配项的输出。 当发现不匹配时,它将调用main函数来处理列表的其余部分。 helper只是将其结果添加到从主要功能获得的结果之前。

略有改进的版本:

(define (compress liste)

  (define (helper in prev out)
     (if (null? in)
        (list (list prev out))
        (if (equal? prev (car in))
          (helper (cdr in) prev (+ 1 out))
          (cons (list prev out) (compress in)))))

    (if (null? liste)
      '()
      (helper (cdr liste) (car liste) 1))
      )

这是尾递归版本:

(define (compress liste)

  (define (helper-1 in out)
    (if (null? in)
      '()
      (helper-2 (cdr in) (car in) 1 out)))

  (define (helper-2 in prev count out)
    (if (null? in)
      (append out (list (list prev count)))
      (if (equal? prev (car in))
        (helper-2 (cdr in) prev (+ 1 count) out)
        (helper-1 in (append out (list (list prev count)))))))

  (helper-1 liste '()))

如错误消息所述,问题位于“第二个if条件的真实谓词上”:

((+ counter 1) compressed-cdr)

在这种情况下, (+ counter 1)应该对一个过程求值,但是对一个数字 我认为问题在于您不知道如何增加计数器。

您的错误谓词有同样的问题:

((cons (car liste) counter) (= counter 0) (compressed-cdr))))))

其中(cons (car liste) counter)产生一个列表,而不是一个过程。

我认为我们无法真正使用此代码。 我建议您看一下萨胡R Sahu)的答案 另外,我可以向您展示尾递归版本,您也可以查看一下。 顺便说一句,这称为游程编码 ,因此我将我的过程称为rle

(define (rle lst)

  (define (newres prv cnt res)
    (case cnt
      ((0)  res) 
      ((1)  (cons prv res)) 
      (else (cons (list prv cnt) res))))

  (let loop ((lst lst) (prv null) (cnt 0) (res null))
    (if (null? lst)
        (if (zero? cnt)
            (reverse res)
            (loop null null 0 (newres prv cnt res)))
        (let ((c (car lst)))
          (if (eq? c prv)
              (loop (cdr lst) prv (add1 cnt) res)
              (loop (cdr lst) c 1 (newres prv cnt res)))))))

为了简单起见,使用“头部前哨把戏”以自上而下的方式构建结果列表:

(define (rle lst)
  (if (null? lst) 
   '()
   (let ((res (list 1)))        ; head sentinel
      (let loop ((p   res)      ; result's last cons cell  
                 (elt (car lst))
                 (cnt 1) 
                 (lst (cdr lst)))
         (if (and (not (null? lst))
                  (equal? elt (car lst)))
            (loop p elt (+ cnt 1) (cdr lst))
            (begin
               (set-cdr! p (list (if (= 1 cnt) elt (list elt cnt))))
               (if (null? lst)
                  (cdr res)     ; skip the head in result, on return
                  (loop (cdr p) (car lst) 1 (cdr lst)))))))))

正如@uselpa解释的那样,这称为游程长度编码。 对于结果的均匀性,我建议对非重复元素使用(x 1)表示形式。

正如其他人所说的那样,错误“错误:应用程序:不是过程;应该是过程”意味着系统希望找到过程但发现了其他东西,因此无法应用它。 Scheme希望找到一个过程作为列表中的第一种形式: (proc args ...) ,并尝试将其应用于参数。 但是在您的代码中,它不是过程,而是其他类型的数据。


如果您的Scheme已左折,或reduce ,则可以执行两次-首先收集统一的结果,然后在反转时应用特殊格式(左折的结果通常以相反的顺序构建):

(define (fold f init lst)            ; if fold is not defined,
   (reduce f init (cons init lst)))  ;   define it in terms of reduce

(define (rle lst)
   (fold (lambda (x acc)             ; NB! MIT-Scheme: (acc x)
             (if (= 1 (cadr x))  (cons (car x) acc)  (cons x acc)))
         '()
      (fold (lambda (x acc)          ; NB! MIT-Scheme: (acc x)
                (if (or (null? acc) (not (equal? (caar acc) x)))
                   (cons (list x 1) acc)
                   (cons (list x (+ (cadar acc) 1)) (cdr acc))))
            '() 
            lst)))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM