我'm working on this procedure which is supposed to return a list of pairs from 2 given lists. So for example (pairs '(1 2 3)'(a b c))应该返回 '((1.a) (2.b) (3.c)) .
到目前为止,这是我的逻辑 . 我将采用每个列表的第一个元素,并以cdr作为新参数再次递归调用该过程 . 我的结果是返回一个这样的列表: (1 a 2 b 3 c)
我的逻辑错在哪里?我知道某个地方有一个列表缺失,但我不是Scheme的专家 .
有什么建议?
(define pairs
(lambda (x y)
(if (or (null? x) (null? y))
'()
(cons (car x)
(cons (car y)
(pairs (cdr x)(cdr y)))))))
(pairs '(1 2 3) '(a b c))
3 回答
您正在寻找的结果应如下所示:
实际上这个结构类似于:
所以你要找的是将对添加到列表而不是像你那样将所有项添加到列表中 . 只是你的结果如下:
您的代码应如下所示:
这段代码可能有效,但并不完美 . 我们可以使代码通过我们创建的列表作为第三个参数来使函数tail递归 .
你有这样的事情:
正如您所看到的,这里因为我们在列表的开头添加了下一个元素,所以我们必须在结尾处反转
lst
. 这里的区别在于,每次调用next
时,都不需要将x和y的每个状态保持在内存中 . 当命名的let将返回时,没有必要将所有值弹回到它调用的位置 . 它只会返回反转列表 .也就是说,我们可以简单地返回
reverse
而不是使用reverse
并使用(append lst (cons (car x) (car y)))
,它会将该对添加到列表的末尾...因为列表是链接列表...以便在列表的末尾添加一些内容,方案必须遍历所有列表项目...这些列表不适合大列表 . 所以解决方案是添加所有内容,最后根据需要重新排序列表 . 反向操作只会发生一次 .请注意,通过评估
(cons 1 3)
,您可以生成一个打印为(1 . 3)
的值 . 但是在您的程序中,您正在执行(cons 1 (cons 3 ...))
,它将在前面的列表中添加1和3 .换句话说:而不是
(cons (car x) (cons (car y) (pairs ...))
使用(cons (cons (car x) (car y) (pairs ...))
.使用
map
简化了很多:测试:
输出: