Multiplying each element of a list with each element of another list in Scheme programming

限于喜欢 提交于 2019-12-11 07:48:22

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!