DrRacket - 使用Lambda的中级学生 - 列表排序

时间:2011-11-19 20:37:51

标签: scheme racket fold

我有一个赋值问题,要求我编写一个函数,使用lambda,它使用一个数字列表并除去每个数字的第一个匹配项。我的功能是相当不错的,除了产生错误的结果!它生成一个列表,其中包含每个数字的最后一次出现。它生成一个列表,其值与正确的列表相同,只是顺序不同。这是我的代码:

    (define (remove-duplicates numlist)
      (foldr (lambda (a b) 
               (cond
                 [(not (member? a b)) (cons a b)]
                 [else b])) empty numlist))

我尝试使用foldl代替foldr,但毫不奇怪,它会生成正确的列表,但反过来。有没有办法生成正确的列表而不需要使用另一个lambda表达式来反转foldl创建的列表?

请记住,这是作业,所以请不要明确答案。

谢谢大家!

1 个答案:

答案 0 :(得分:1)

从语义上考虑折叠器的行为方式。它从列表最右边的元素开始,然后执行折叠,向左移动。这意味着在你的lambda函数中,a表示直接位于如此远折叠列表左侧的元素,而b表示将所有内容折叠到列表元素右侧的结果{{ 1}}。考虑到这一点,请考虑:

a

您检查列表[(not (member? a b)) (cons a b)] [else b] 是否已包含b。如果是,则放弃a,保持a不变。这解释了为什么你的代码保留最后(最右边)的出现,而不是第一次出现。如果您希望执行正确的折叠,则必须更改逻辑。您需要以某种方式“清除”其包含的有问题元素b的{​​{1}}。

b

这样,您最终只会保留每个唯一元素的最左侧,而不是最右侧。同时执行a[(not (member? a b)) (cons a b)] [else (cons a (purge a b))] 可能是明智的,因为它们都必须遍历列表;这需要额外的重构。

请注意,由于该函数无论如何需要 O(n 2 时间,因此添加 O(n)确实不会影响时间复杂度)member?版本相反。