如何实现此功能
如果获得两个列表(A B C),(D E)
和返回列表(A D B D C D A E B E C E)
列表元素都是整数,结果列表的元素顺序是免费的
我尝试了
(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))))))))
但是它返回错误,因为结果为'()
我不知道如何解决这个问题,请帮助我
数据转换方法:
(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)
您去这里:
(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
s的for*/list
),它将自动为您完成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)
在方案中,不建议使用诸如集合的函数!或附加!因为它会导致数据更改或可变,而不是funcitonal编程样式。
应该这样:
(定义(添加列表val lst) (if(null?lst)'() (cons(list val(car lst))(附加列表val(cdr lst))))))))))(定义(添加列表LST0 LST1) (if(null?lst0)'() (附录(ADD-ONE-LIST(CAR LST0)LST1) (添加列表(CDR LST0)LST1)))))))
首先理解函数添加列表,它递归地自称为自身,每次构建LST的Val和拳头元素到列表中,并将其作为最终答案。
添加列表函数就像添加列表一样。
(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)
与威尔和园林一起进行。如果您要使用方案,则可能会使用惯用方案。
用来构建列表对我来说有点奇怪。(列表的综合性更适合)通常用于诱导顺序副作用。那和rsr5不能定义/列表或*/列表。
flatmap是一个相当常见的功能范式,在其中您使用附录而不是弊端来构建列表以避免嵌套和空的sublists
它不起作用,因为诸如append
之类的功能不会突变容器。您可以通过append!
这样的突变功能来解决问题。通常功能突变为!
的名称,例如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)))