Умножение каждого элемента списка на каждый элемент другого списка в программировании схемы - PullRequest
1 голос
/ 28 ноября 2011

Я пытаюсь сделать следующее в схеме:

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 .. и т. Д.

У меня проблемы с внедрением этого в Схему. Я попытался использовать функцию map, но, похоже, это работает не так, как я хочу. Есть идеи?

Ответы [ 3 ]

3 голосов
/ 28 ноября 2011

Оскар дал очень полный ответ на этот вопрос, но я хотел добавить две небольшие заметки:

Диалект схемы Ракетка имеет красивую встроенную форму под названием for*/list, которая делает именно такие вещи:

(for*/list ([i '(1 2 3 4)]
            [j '(2 4 6 8)])
  (* i j))

Кроме того, вместо использования своей собственной или библиотечной функции flatten в решении с вложенными картами, вы можете заменить внешний map на append-map из SRFI-1 . Конечно, есть и много других способов; -)

3 голосов
/ 28 ноября 2011

Начнем с определения двух списков ввода, я переименовал их, так как list является встроенной процедурой в схеме и не является хорошей идеей перезаписать ее):

(define l '(1 2 3 4))
(define l1 '(2 4 6 8))

Япри условии, что вы хотите, чтобы ваш список результатов был «плоским» - например, он не содержит списков элементов, только элементы (если у вас все в порядке с наличием списка списков в l2, просто удалите вызов flatten ниже).Для этого нам нужно определить процедуру 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 процедуры - взгляните на раздел вложенных отображений в книге 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 голос
/ 13 декабря 2011

Не могу поверить, что никто не дал самый простой ответ: вложенное использование map:

(append-map (lambda (x)
              (map (lambda (y) (* x y))
                   (list 2 4 8 6)))
            (list 1 2 3 4))

append-map - это простой вариант map, предполагающий, что функция отображения возвращаетсписок, поэтому он объединяет все списки результатов.Это библиотечная функция в большинстве серьезных систем Scheme (в библиотека SRFI-1 ), но вот простое неполное определение (полное определение будет обрабатывать несколько списков аргументов):

(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)))))
...