问题
i am trying to do the following in 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]);
}
}
as seen in the code above, I am trying to multiply each element of the first list with every element in the second list. So 1*2, 1*4, 1*6, 1*8, then going to the next element, 2*2,2*4.. etc.
I am having trouble implementing this into Scheme. I tried using the map
function but this doesn't seem to work the way I want it to. Any ideas?
回答1:
We start by defining the two input lists, I renamed them since list
is a built-in procedure in Scheme and is not a good idea to overwrite it):
(define l '(1 2 3 4))
(define l1 '(2 4 6 8))
I'm assuming that you want your result list to be "flat" - e.g., it doesn't contain lists of elements, only elements (if you're ok with having a list of lists in l2
, simply delete the call to flatten below). For that, we need to define the flatten
procedure:
(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))))))
Finally, the problem at hand. It's simple once you understand how to nest two map
procedures - take a look at the nested mappings section in the book SICP.
(define l2
(flatten
(map (lambda (i)
(map (lambda (j)
(* i j))
l1))
l)))
At this point, l2
contains the expected answer:
(2 4 6 8 4 8 12 16 6 12 18 24 8 16 24 32)
回答2:
Óscar has given a very complete answer to this question, but I wanted to add two minor notes:
The Scheme dialect Racket has a nice built-in form called for*/list
which does exactly this sort of thing:
(for*/list ([i '(1 2 3 4)]
[j '(2 4 6 8)])
(* i j))
Also, instead of using your own or the library's flatten
function in the nested-maps solution, you could replace the outer map
with append-map
from SRFI-1. There are plenty of other ways too, of course ;-)
回答3:
I can't believe nobody has given the most straightforward answer: nested uses of map
:
(append-map (lambda (x)
(map (lambda (y) (* x y))
(list 2 4 8 6)))
(list 1 2 3 4))
append-map
is a simple variant of map
that assumes that the mapping function returns a list, so it concatenates all the result lists. This is a library function in most serious Scheme systems (it's in the SRFI-1 library), but here's a simple, incomplete definition (a complete definition would handle multiple argument lists):
(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)))))
来源:https://stackoverflow.com/questions/8289139/multiplying-each-element-of-a-list-with-each-element-of-another-list-in-scheme-p