链接映射增加列表嵌套级别
Chaining maps increasing list nesting level
我正在尝试执行以下 Python 到 Scheme 的转换以练习嵌套循环:
>>> def possible_triads(n1, n2, n3):
for num1 in n1:
for num2 in n2:
for num3 in n3:
print (num1, num2, num3)
>>> possible_triads([1,2], [3,4], [5,6])
(1, 3, 5)
(1, 3, 6)
(1, 4, 5)
(1, 4, 6)
(2, 3, 5)
(2, 3, 6)
(2, 4, 5)
(2, 4, 6)
这是我在 Scheme 中的尝试:
(define (possible-triads n1 n2 n3)
(map (lambda (num1)
(map (lambda (num2)
(map (lambda (num3) (list num1 num2 num3))
n3))
n2))
n1))
(possible-triads '(1 2) '(3 4) '(5 6))
;((((1 3 5) (1 3 6)) ((1 4 5) (1 4 6))) (((2 3 5) (2 3 6)) ((2 4 5) (2 4 6))))
现在,很接近了,但我想知道为什么每个 map
都会产生一个新的列表级别?例如,我怎样才能得到结果只是三元组的列表,例如:
(
(1 3 5)
(1 3 6)
(1 4 5)
(1 4 6)
(2 3 5)
(2 3 6)
(2 4 5)
(2 4 6)
)
python for
循环不会自动将其结果收集到像 map
这样的列表中,因此您看不到嵌套。 Scheme 中的等价物是 for-each
,它会因副作用而循环,而不是收集结果。就像在你的 Python 函数中一样,你应该在最里面的循环中打印列表,而不是 return 它。
(define (possible-triads n1 n2 n3)
(for-each (lambda (num1)
(for-each (lambda (num2)
(for-each (lambda (num3)
(display (list num1 num2 num3))) n3)) n2)) n1))
尝试从类似 Algol 的语言(如 Python)中提取一些代码并将其“翻译”成 lispy 代码通常不是一个好主意。正如 所提到的,Python 代码没有创建结果列表,它只是将结果作为副作用打印出来; Scheme 代码实际上是在创建一个结果列表。发布的代码中的问题是最里面的 map
创建了一个列表列表,中间的 map
从中创建了另一个列表列表,最外面的 map
创建了另一个列表列表从它收到的嵌套列表中。
您可以通过策略性地附加映射操作的结果来完成这项工作:
(define (possible-triads xs ys zs)
(apply append
(map (lambda (x)
(apply append
(map (lambda (y)
(map (lambda (z) (list x y z))
zs))
ys)))
xs)))
这里最里面的 map
在 zs
之上创建了一个列表列表。中间 map
使用该结果创建列表列表的列表,将其附加在一起以获得列表列表。最后最外层的map
使用里面的两个映射操作提供的lists的lists创建另一个lists的lists的lists,将它们追加在一起得到最终的结果作为lists的lists。
请注意,在这样的循环中使用 append
通常不是一个好主意;由于 append
本身具有线性时间复杂度,因此这些类型的解决方案往往是二次或更糟的。
nested-looping.rkt> (possible-triads '(1 2) '(3 4) '(5 6))
'((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
我正在尝试执行以下 Python 到 Scheme 的转换以练习嵌套循环:
>>> def possible_triads(n1, n2, n3):
for num1 in n1:
for num2 in n2:
for num3 in n3:
print (num1, num2, num3)
>>> possible_triads([1,2], [3,4], [5,6])
(1, 3, 5)
(1, 3, 6)
(1, 4, 5)
(1, 4, 6)
(2, 3, 5)
(2, 3, 6)
(2, 4, 5)
(2, 4, 6)
这是我在 Scheme 中的尝试:
(define (possible-triads n1 n2 n3)
(map (lambda (num1)
(map (lambda (num2)
(map (lambda (num3) (list num1 num2 num3))
n3))
n2))
n1))
(possible-triads '(1 2) '(3 4) '(5 6))
;((((1 3 5) (1 3 6)) ((1 4 5) (1 4 6))) (((2 3 5) (2 3 6)) ((2 4 5) (2 4 6))))
现在,很接近了,但我想知道为什么每个 map
都会产生一个新的列表级别?例如,我怎样才能得到结果只是三元组的列表,例如:
(
(1 3 5)
(1 3 6)
(1 4 5)
(1 4 6)
(2 3 5)
(2 3 6)
(2 4 5)
(2 4 6)
)
python for
循环不会自动将其结果收集到像 map
这样的列表中,因此您看不到嵌套。 Scheme 中的等价物是 for-each
,它会因副作用而循环,而不是收集结果。就像在你的 Python 函数中一样,你应该在最里面的循环中打印列表,而不是 return 它。
(define (possible-triads n1 n2 n3)
(for-each (lambda (num1)
(for-each (lambda (num2)
(for-each (lambda (num3)
(display (list num1 num2 num3))) n3)) n2)) n1))
尝试从类似 Algol 的语言(如 Python)中提取一些代码并将其“翻译”成 lispy 代码通常不是一个好主意。正如 map
创建了一个列表列表,中间的 map
从中创建了另一个列表列表,最外面的 map
创建了另一个列表列表从它收到的嵌套列表中。
您可以通过策略性地附加映射操作的结果来完成这项工作:
(define (possible-triads xs ys zs)
(apply append
(map (lambda (x)
(apply append
(map (lambda (y)
(map (lambda (z) (list x y z))
zs))
ys)))
xs)))
这里最里面的 map
在 zs
之上创建了一个列表列表。中间 map
使用该结果创建列表列表的列表,将其附加在一起以获得列表列表。最后最外层的map
使用里面的两个映射操作提供的lists的lists创建另一个lists的lists的lists,将它们追加在一起得到最终的结果作为lists的lists。
请注意,在这样的循环中使用 append
通常不是一个好主意;由于 append
本身具有线性时间复杂度,因此这些类型的解决方案往往是二次或更糟的。
nested-looping.rkt> (possible-triads '(1 2) '(3 4) '(5 6))
'((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))