clojure, как выполнить функцию на элементах двух последовательностей одновременно? - PullRequest
9 голосов
/ 03 февраля 2012

В Clojure, каков наилучший способ для одновременной итерации на двух последовательностях и вызова функции на двух работающих элементах? Например:

(def a (range 3))
(def b (range 100 103))
(defn my-func [] ...) ;some custom code

Код должен выполнить my-func 3 раза, например:

(my-func 0 100)
(my-func 1 101)
(my-func 2 102)

Как мне этого добиться, не задавая ни одной функции или макроса?

Ответы [ 3 ]

16 голосов
/ 03 февраля 2012

map - это именно то, что вам нужно, оно берет функцию и любое количество последовательностей и вызывает их так, как вы хотите.

(def a (range 3))
(def b (range 100 103))
user=> a
(0 1 2)
user=> b
(100 101 102)

user=> (defn my-func [a b] (str a ":" b))
#'user/my-func

user=> (my-func 1 2)
"1:2"

user=> (map my-func a b)
("0:100" "1:101" "2:102")

и потому что map ленив, если вы хотите, чтобы функция действительно выполнялась сейчас:

(doall (map my-func a b))
3 голосов
/ 03 февраля 2012

Вы также можете попробовать

(doseq [[x y] (map list my-list1 my-list2)]
  (println x y))

(map list list-2 list-2) создает список, где первый элемент представляет собой список первых элементов входных списков, второй элемент представляет собой список вторых элементов,...

Затем мы перебираем список, используя деструктуризацию Clojure для извлечения элементов из исходных списков.

В общем, вы хотите map, если хотите использовать возвращаемое значениефункция, которую вы применяете.Если вы просто выполняете функцию для ее побочных эффектов, я обычно использую doseq.Этот случай усложняется тем фактом, что map работает параллельно, в то время как doseq выполняет итерацию по декартову произведению из списков, которые ему даны, поэтому вам нужно и map, и doseq, чтобы получитьповедение, которое мы хотим.

0 голосов
/ 26 марта 2016

Альтернатива решению (doseq ... (map, если вы хотите использовать парную итерацию вместо декартового произведения, вы также можете объединить partition с interleave следующим образом:

> (def a (range 0 3))
> (def b (range 100 103))
> (interleave a b)
(0 100 1 101 2 102)
> (partition 2 (interleave a b))
((0 100) (1 101) (2 102))

Вызов partitionобеспечивает (ленивый) последовательность пар.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...