【问题标题】:How to remove non-duplicate elements from a list in Scheme?如何从 Scheme 中的列表中删除不重复的元素?
【发布时间】:2011-04-22 01:50:45
【问题描述】:

给定一个列表,

(define ll '(a a a b c c c d e e e e))

我想删除所有不重复的元素,只留下一个重复的副本,即删除后,结果将是

(a c e)

我的算法是:

  • 遍历列表,比较当前元素和下一个元素。

    • 如果它们相等,则 cons 将当前元素与下一个递归调用的列表。例如,

      (a a a b c)
      

      从左向右移动,遇到aa

      (cons a (remove-nondup (cddr lst)))
      
    • 否则,跳过当前和下一个元素。

      (remove-nondup (cddr lst))
      

我遇到的问题是

(define (remove-nondup lst)
  (if (>= (length lst) 2)
      (if (eq? (car lst) (cadr lst))
          (cons (car lst) (remove-nondup (cdr lst)))
          (remove-nondup (cddr lst)))
      lst))

我遇到的问题是,如果连续元素超过 3 个,我无法跟踪前一个元素。所以我想知道我应该使用另一个程序来删除所有重复项吗?或者我可以将它们放入一个程序中?

所以我目前的替代解决方案是,

(define (remove-dup lst)
  (if (>= (length lst) 2)
      (if (eq? (car lst) (cadr lst))
          (cons (car lst) (remove-dup (cddr lst)))
          (cons (car lst) (remove-dup (cdr lst))))
      lst))

(define (remove-nondup-helper lst)
  (if (>= (length lst) 2)
      (if (eq? (car lst) (cadr lst))
          (cons (car lst) (remove-nondup-helper (cdr lst)))
          (remove-nondup (cddr lst)))
      lst))

; call the helper function and remove-dup
(define (remove-nondup lst)
  (remove-dup (remove-nondup-helper lst)))

【问题讨论】:

    标签: scheme


    【解决方案1】:

    这是我的解决方案:首先,获取bagify(任何版本都可以)。那么:

    (define (remove-singletons lst)
      (define (singleton? ass)
        (< (cdr ass) 2))
      (map car (remove singleton? (bagify lst))))
    

    remove 来自 SRFI 1。如果您使用的是 Racket,请先运行 (require srfi/1)。或者,使用这个简单的定义:

    (define remove #f)   ; Only needed in Racket's REPL
    (define (remove pred lst)
      (cond ((null? lst) lst)
            ((pred (car lst)) (remove pred (cdr lst)))
            (else (cons (car lst) (remove pred (cdr lst))))))
    

    【讨论】:

    • 你能给出一个没有预定义库的解决方案吗?在尝试使用库函数之前,我试图先熟悉 Scheme。谢谢。
    • @Chan:我添加了remove 的定义。我无法避免在不使功能糟糕的情况下使用它,所以这是下一个最好的事情。
    【解决方案2】:

    这是一种仅使用标准库函数和尾调用的方法,尽管它执行线性搜索以查看是否已经看到或放入结果中的项目:

    (define remove-nondup
      (λ (ls)
        (reverse
          (let loop ([ls ls] [found '()] [acc '()])
            (cond
              [(null? ls)
                acc]
              [(memq (car ls) found)
                (loop (cdr ls)
                      found
                      (if (memq (car ls) acc)
                          acc
                          (cons (car ls) acc)))]
              [else
                (loop (cdr ls)
                      (cons (car ls) found)
                      acc)])))))
    
    (remove-nondup '(a a a b c c c d e e e e)) =>
      (a c e)
    (remove-nondup '(a a a b c c c d e e e e f a a f)) =>
      (a c e f)
    

    loop 是一个“命名的 let”:一种方便的方法,可以将辅助过程粘贴到过程中而不会产生大量语法混乱。

    如果您只想将连续重复项缩小到一个项目,并且仅在它们不连续出现两次时才删除它们,那么这里有一种方法可以“记住”两个单元格前的项目而不搜索它,并且只使用尾调用:

    (define remove-nonconsecdup
      (λ (ls)
        (reverse
          (letrec (
              [got1 (λ (ls prev acc)
                      (cond
                        [(null? ls)
                          acc]
                        [(eq? prev (car ls))
                          (got2 (cdr ls) (cons prev acc))]
                        [else
                          (got1 (cdr ls) (car ls) acc)]))]
              [got2 (λ (ls acc)
                      (cond
                        [(null? ls)
                          acc]
                        [(eq? (car acc) (car ls))
                          (got2 (cdr ls) acc)]
                        [else
                          (got1 (cdr ls) (car ls) acc)]))])
            (if (null? ls)
                '()
                (got1 (cdr ls) (car ls) '()))))))
    
    (remove-nonconsecdup '(a a a b c c c d e e e e)) =>
      (a c e)
    (remove-nonconsecdup '(a a a b c c c d e e e e f a a f)) =>
      (a c e a)
    

    我不喜欢颠倒列表,但调用reverse 很容易。如果reverse 完成的额外cons'ing 是一个问题,您可以进行非尾调用或将项目粘贴在列表末尾,但这更难有效地完成(但使用非标准库宏很容易) .

    【讨论】:

      猜你喜欢
      • 2012-11-13
      • 1970-01-01
      • 2017-09-03
      • 2018-01-01
      • 2015-01-05
      • 1970-01-01
      • 2012-05-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多