Scheme - 从列表中删除子列表

时间:2013-01-10 04:20:02

标签: list scheme r5rs

我有一份清单,例如。 ((x y z) (y z) (x y)),我想知道在R5RS Scheme中是否有办法只删除此列表中的子列表:例如。 (y z)是一个子列表,因为它已经在(x y z))内部,在我们的示例中会((x y z))

这可能比我想象的要复杂得多,但我猜它会利用地图或过滤器,但我不确定你是怎么用这种方式“清理”整个列表的。

1 个答案:

答案 0 :(得分:1)

问题比看起来有点棘手。我将使用Racket,因此可能会出现一些非标准功能,但如果您遇到基本的R5RS程序,那么自己实现起来并不是特别困难(如果有疑问,请查看documentation)。另外请注意,我更喜欢我的解决方案的函数式编程风格,因此会有map s,filter和其他更高阶的过程。

首先,我们需要一种方法来测试列表是否是任何位置的另一个的子列表;我使用来自this post的想法来生成所有可能的连续子列表:

(define (inits lst)
  (let loop ((acc '())
             (n (length lst)))
    (if (negative? n)
        acc
        (loop (cons (take lst n) acc) (sub1 n)))))

(define (tails lst)
  (let loop ((acc '())
             (n (length lst)))
    (if (negative? n)
        acc
        (loop (cons (drop lst n) acc) (sub1 n)))))

(define (contiguous-sublists lst)
  (cons '()
        (remove* '(())
                 (append-map inits (tails lst)))))

(define (sublist? l1 l2)
  (if (member l1 (contiguous-sublists l2)) #t #f))

现在是实际的程序,请注意我假设输入列表是无副本的:

(define (remove-sublists lst)
  (filter
   (lambda (l1)
     (andmap
      (lambda (l2)
        (not (sublist? l1 l2)))
      (remove l1 lst)))
   lst))

按预期工作:

(remove-sublists '((x y z) (y z) (x y)))
=> '((x y z))