我正在尝试在Scheme中执行以下操作:
List<int> list = new List<int>();
List<int> list1 = new List<int>();
List<int> list2 = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list1.Add(2);
list1.Add(4);
list1.Add(6);
list1.Add(8);
for (int i = 0; i < list.Count; i++)
{
for (int p = 0; p < list1.Count; p++)
{
list2.Add(list[i] * list1[p]);
}
}
如上面的代码所示,我试图将第一个列表的每个元素与第二个列表中的每个元素相乘。所以1 * 2,1 * 4,1 * 6,1 * 8,然后转到下一个元素,2 * 2,2 * 4等。
我无法在Scheme中实现此功能。我尝试使用map
函数,但这似乎不像我想要的那样工作。有什么想法吗?
答案 0 :(得分:3)
我们首先定义两个输入列表,我重命名它们,因为list
是Scheme中的内置过程,并且不好覆盖它:)
(define l '(1 2 3 4))
(define l1 '(2 4 6 8))
我假设你希望你的结果列表是“平坦的” - 例如,它不包含元素列表,只包含元素(如果你在l2
中有一个列表列表就可以了,只需删除下面展平的电话)。为此,我们需要定义flatten
过程:
(define (atom? x)
(and (not (pair? x)) (not (null? x))))
(define (flatten lst)
(cond ((null? lst) empty)
((atom? lst) (list lst))
(else (append (flatten (car lst))
(flatten (cdr lst))))))
最后,手头的问题。一旦您了解了如何嵌套两个map
程序,这很简单 - 请查看书籍nested mappings中的SICP部分。
(define l2
(flatten
(map (lambda (i)
(map (lambda (j)
(* i j))
l1))
l)))
此时,l2
包含预期答案:
(2 4 6 8 4 8 12 16 6 12 18 24 8 16 24 32)
答案 1 :(得分:3)
Óscar对这个问题给出了非常完整的答案,但我想补充两个小调:
方案方言Racket有一个很好的内置形式叫for*/list
,它完全可以做到这一点:
(for*/list ([i '(1 2 3 4)]
[j '(2 4 6 8)])
(* i j))
此外,您可以在嵌套地图解决方案中使用自己的库或flatten
函数,而不是从SRFI-1将map
替换为append-map
。当然,还有很多其他方法; - )
答案 2 :(得分:1)
我无法相信没有人给出最直接的答案:map
的嵌套用法:
(append-map (lambda (x)
(map (lambda (y) (* x y))
(list 2 4 8 6)))
(list 1 2 3 4))
append-map
是map
的一个简单变体,它假定映射函数返回一个列表,因此它连接所有结果列表。这是最严重的Scheme系统中的库函数(它在the SRFI-1 library中),但是这里是一个简单的,不完整的定义(一个完整的定义将处理多个参数列表):
(define (append-map f xs)
(concat (map f xs)))
;;;
;;; Turns a list of lists into a list by appending all the top-level sublists.
;;; This is also a common library function.
;;;
(define (concat lists)
(if (null? lists)
'()
(append (car lists)
(concat (cdr lists)))))