【发布时间】:2013-01-10 04:20:01
【问题描述】:
我有一个列表列表,例如。 ((x y z) (y z) (x y)),我想知道在R5RS Scheme 中是否有一种方法可以只从该列表中删除子列表:例如。 (y z) 是一个子列表,因为它已经在“内部”(x y z)),在我们的示例中,它会留下 ((x y z))。
这可能比我想象的要复杂,但我猜它会使用地图或过滤器,但我不确定你会如何以这种方式“清理”整个列表。
【问题讨论】:
我有一个列表列表,例如。 ((x y z) (y z) (x y)),我想知道在R5RS Scheme 中是否有一种方法可以只从该列表中删除子列表:例如。 (y z) 是一个子列表,因为它已经在“内部”(x y z)),在我们的示例中,它会留下 ((x y z))。
这可能比我想象的要复杂,但我猜它会使用地图或过滤器,但我不确定你会如何以这种方式“清理”整个列表。
【问题讨论】:
这个问题比看起来要复杂一些。我将使用 Racket,因此可能会出现一些非标准功能,但如果您坚持使用基本的 R5RS 程序(如有疑问,请查看documentation)。另请注意,我的解决方案更喜欢函数式编程风格,因此会有maps、filters 和其他高阶过程。
首先,我们需要一种方法来测试一个列表是否是另一个在任何位置的子列表;我正在使用来自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))
【讨论】: