如何实现此功能
如果得到两个列表(a b c),(d e)
并返回列表(a + d b + d c + d a + e b + e c + e)
list元素全是整数,结果列表的元素顺序是免费的
我试过这个
(define (addlist L1 L2)
(define l1 (length L1))
(define l2 (length L2))
(let ((result '()))
(for ((i (in-range l1)))
(for ((j (in-range l2)))
(append result (list (+ (list-ref L1 i) (list-ref L2 j))))))))
但它返回错误,因为结果是'()
我不知道如何解决这个问题请帮帮我
答案 0 :(得分:2)
数据转换方法:
(a b c ...) (x y ...)
1. ==> ( ((a x) (b x) (c x) ...) ((a y) (b y) (c y) ...) ...)
2. ==> ( (a x) (b x) (c x) ... (a y) (b y) (c y) ... ...)
3. ==> ( (a+x) (b+x) ... )
(define (addlist L1 L2)
(map (lambda (r) (apply + r)) ; 3. sum the pairs up
(reduce append '() ; 2. concatenate the lists
(map (lambda (e2) ; 1. pair-up the elements
(map (lambda (e1)
(list e1 e2)) ; combine two elements with `list`
L1))
L2))))
测试(在MIT-Scheme中):
(addlist '(1 2 3) '(10 20))
;Value 23: (11 12 13 21 22 23)
你可以简化这个,所以没有单独的第3步吗?
我们可以在这里进一步分离出不同的比特和片段,如
(define (bind L f) (join (map f L)))
(define (join L) (reduce append '() L))
(define yield list)
然后,
(bind '(1 2 3) (lambda (x) (bind '(10 20) (lambda (y) (yield (+ x y))))))
;Value 13: (11 21 12 22 13 23)
(bind '(10 20) (lambda (x) (bind '(1 2 3) (lambda (y) (yield (+ x y))))))
;Value 14: (11 12 13 21 22 23)
答案 1 :(得分:1)
你走了:
(define (addlist L1 L2)
(for*/list ((i (in-list L1)) (j (in-list L2)))
(+ i j)))
> (addlist '(1 2 3) '(10 20))
'(11 21 12 22 13 23)
诀窍是使用for/list
(或嵌套for*/list
s时为for
),它会自动为您执行append
。另请注意,您可以遍历列表,无需使用索引。
要使结果“反过来”,反转L1和L2:
(define (addlist L1 L2)
(for*/list ((i (in-list L2)) (j (in-list L1)))
(+ i j)))
> (addlist '(1 2 3) '(10 20))
'(11 12 13 21 22 23)
答案 2 :(得分:1)
在方案中,不建议使用像set这样的功能!或追加! 因为它导致数据变化或变量,而不是功能编程风格。
应该这样:
(define (add-one-list val lst) (if (null? lst) '() (cons (list val (car lst)) (add-one-list val (cdr lst))))) (define (add-list lst0 lst1) (if (null? lst0) '() (append (add-one-list (car lst0) lst1) (add-list (cdr lst0) lst1))))
首先理解函数add-one-list,它递归地调用自身,并且每次将lst的val和第一元素构建到列表中,并且CONS /将它作为最终答案累积。
add-list function就像add-one-list。
答案 3 :(得分:1)
(define (addlist L1 L2)
(flatmap (lambda (x) (map (lambda (y) (+ x y)) L1)) L2))
(define (flatmap f L)
(if (null? L)
'()
(append (f (car L)) (flatmap f (cdr L)))))
1 ]=> (addlist '(1 2 3) '(10 20))
;Value 2: (11 12 13 21 22 23)
与Will和Procras一起参加此活动。如果您打算使用方案,不妨使用惯用方案。
使用for来构建列表对我来说有点奇怪。 (列表推导更适合)因为通常用于引起顺序副作用。那和RSR5没有定义for / list或for * / list。
Flatmap是一个相当常见的功能范例,您可以使用append而不是cons来构建列表以避免嵌套和空的子列表
答案 4 :(得分:0)
它不起作用,因为像append
这样的函数不会改变容器。你可以使用像append!
这样的变异函数来解决你的问题。通常,mutate函数的名称中包含!
,如set!
等。
但是如果不做突变就可以实现这一目标。您必须更改算法才能将结果发送到下一次迭代。像这样:
(let loop ((result '()))
(loop (append result '(1)))
正如您所看到的,当循环被调用时,结果将是:
'()
'(1)
'(1 1)
'(1 1 1)
....
遵循此逻辑,您应该能够更改算法以使用此方法而不是for
循环。您必须传递更多参数才能知道何时必须退出并返回result
。
我今天晚些时候会尝试添加更完整的答案。
这是append!
的一个实现,我刚才写道:
(define (append! lst1 lst2)
(if (null? (cdr lst1))
(set-cdr! lst1 lst2)
(append! (cdr lst1) lst2)))