打印列表的相邻副本(方案)

Print adjacent duplicates of a list (scheme)

我正在尝试创建一个函数,该函数 return 是列表的相邻副本,例如(dups '(1 2 1 1 1 4 4) 应该 return 列表 ( 1 4).

这是我到目前为止想出的代码:

(define (dups lst)
    (if (equal? (car lst)(car(cdr lst)))
        (cons(cdr lst) '())
        (dups(cdr lst))))

此函数不会 return 所有相邻的重复项,它只会 return 第一个相邻的重复项! 我怎样才能修复它,使它 return 包含列表的所有相邻副本?

谢谢。

一旦您的代码找到重复项,它就会停止处理列表的其余部分:当 if 测试为真时,它会产生 (cons (cdr lst) '())。无论是否找到重复项,它仍应调用 dups 来处理列表的其余部分。

此外:如果您的列表没有重复项,它将 运行 惹上麻烦。

这里有一个比其他人发布的更简单的解决方案:

(define (dups lst)
    (if (< (length lst) 2)
        ; No room for duplicates
        '()
        ; Check for duplicate at start
        (if (equal? (car lst) (cadr lst))
            ; Starts w/ a duplicate
            (if (or (null? (cddr lst)) ; end of list
                    (not (equal? (car lst) (caddr lst)))) ; non-matching symbol next
                ; End of run of duplicates; add to front of what we find next
                (cons (car lst) (dups (cdr lst)))
                ; Othersise keep looking
                (dups (cdr lst)))
            ; No duplicate at start; keep looking
            (dups (cdr lst)))))

基本上这归结为只保留与前一个相同但与下一个不同的元素。

这是一个使用命名 let 的示例实现。

(define (adj-dups lst)
      (let loop ((lst (reverse (cons (gensym) lst)))
                 (e-2 (gensym))
                 (e-1 (gensym))
                 (acc '()))
        (if (null? lst) 
            acc
            (let ((e-0 (car lst)))
              (loop (cdr lst)
                    e-1
                    e-0
                    (if (and (eqv? e-2 e-1) (not (eqv? e-1 e-0)))
                        (cons e-1 acc)
                        acc))))))

(gensym) 在这里派上用场,因为它是一种方便的方法,可以用不同于其他任何东西的东西初始化工作变量,并用需要添加的虚拟元素填充初始列表,以便我们不要错过最后一个元素。 测试:

> (adj-dups '())
'()
> (adj-dups '(1 1 4 4 1 1))
'(1 4 1)
> (adj-dups '(1 1 1 1 1))
'(1)
> (adj-dups '(1 2 1 1 1 4 4))
'(1 4)
> (adj-dups '(2 3 3 4 4 4 5))
'(3 4)

我能想到的解决这个问题的最直接的方法是使用一个带有额外变量的内部过程来跟踪先前的元素是什么,以及一个布尔值来跟踪元素是否重复。然后,您可以在 helper 和 main 函数之间进行相互递归,以一次构建一个重复元素的答案。

(define (dups lst)
   (define (dups-helper x repeat? L)
      (cond ((null? L)
             (if repeat? 
                 (list x)
                 '()))
            ((equal? x (car L))
             (dups-helper x #t (cdr L)))
            (else 
             (if repeat?
                 (cons x (dups L))
                 (dups L)))))
  (if (null? lst)
      '()
      (dups-helper (car lst) #f (cdr lst))))

(dups (list 1 1 4 4 5 6 3 3 1))
 ;Value 43: (1 4 3)