我有一个赋值问题,要求我编写一个函数,使用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
创建的列表?
请记住,这是作业,所以请不要明确答案。
谢谢大家!
答案 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?
版本相反。