Scheme - using foldr inside map and making the foldr proc use the current element given from the map iteration
我正在尝试编写以下函数,该函数获取 2 个列表并返回这些列表的笛卡尔积。
这是我写的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ;; Signature: mix-rows(rows1 rows2) ;; Purpose: returns a list of rows of the cartesian product of both rows ;; Type: [ List(Row) * List(Row) -> List(Row) ] ;; Tests: ;; (mix-rows (list '(10 11) '(20 21)) (list '('u 'v) '('p 'q))) ;; ==> ((10 11 'u 'v) ;; (10 11 'p 'q) ;; (20 21 'u 'v) ;; (20 21 'p 'q)) (define mix-rows (lambda (rows1 rows2) (map (lambda (row1) (foldr (lambda (row2) (append row1 row2)) '() rows2)) rows1))) |
由于某种原因,最后一个 lambda 无法识别从遍历 rows1 的函数映射中给出的 row1。
我希望最后一个 lambda 遍历 rows2 并将每个元素附加到 row1 并且在附加所有 rows2 元素之后 row1 将更改为 rows1 中的下一个元素。
为什么 lambda 不能识别 row1?
谢谢。
首先,如果你想要的只是一个
1 2 3 4 | > (cartesian-product (list '(10 11) '(20 21)) (list '('u 'v) '('p 'q))) '(((10 11) ('u 'v)) ((10 11) ('p 'q)) ((20 21) ('u 'v)) ((20 21) ('p 'q))) |
您的测试用例与此略有不同,因为您的测试用例拼接了内部列表而这没有。但是,如果这是您需要的,您可以使用
1 2 3 4 5 6 | > (define (mix-rows rows1 rows2) (map append* (cartesian-product rows1 rows2))) > (mix-rows (list '(10 11) '(20 21)) (list '('u 'v) '('p 'q))) '((10 11 'u 'v) (10 11 'p 'q) (20 21 'u 'v) (20 21 'p 'q)) |
虽然如果你想从头开始设计它,你的实现的问题是
1 2 3 4 5 6 7 | (define mix-rows (lambda (rows1 rows2) (map (lambda (row1) (map (lambda (row2) (append row1 row2)) rows2)) rows1))) |
虽然,这仍然使您的测试用例失败,产生
1 2 3 4 | > (mix-rows (list '(10 11) '(20 21)) (list '('u 'v) '('p 'q))) '(((10 11 'u 'v) (10 11 'p 'q)) ((20 21 'u 'v) (20 21 'p 'q))) |
要摆脱额外的嵌套列表层,您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ;; Signature: mix-rows(rows1 rows2) ;; Purpose: returns a list of rows of the cartesian product of both rows ;; Type: [ List(Row) * List(Row) -> List(Row) ] ;; Tests: ;; (mix-rows (list '(10 11) '(20 21)) (list '('u 'v) '('p 'q))) ;; ==> ((10 11 'u 'v) ;; (10 11 'p 'q) ;; (20 21 'u 'v) ;; (20 21 'p 'q)) (define mix-rows (lambda (rows1 rows2) (append* (map (lambda (row1) (map (lambda (row2) (append row1 row2)) rows2)) rows1)))) |
但是,如果您想要一个真正的笛卡尔积,而不拼接行,您可以通过将
1 2 3 4 5 6 7 8 | (define mix-rows (lambda (rows1 rows2) (append* (map (lambda (row1) (map (lambda (row2) (list row1 row2)) rows2)) rows1)))) |
然后它匹配