如何同时在两个seqs的元素上执行函数?

时间:2012-02-02 23:26:50

标签: clojure

在Clojure中,在两个seq上并发迭代并在两个运行元素上调用函数的最佳方法是什么? 例如:

(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 个答案:

答案 0 :(得分:16)

map正是您所需要的,它需要一个函数和任意数量的seq,并按照您的意愿调用它们。

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

答案 1 :(得分:3)

您也可以尝试

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

(map list list-2 list-2)创建一个列表,其中第一个元素是输入列表的第一个元素的列表,第二个元素是第二个元素的列表,...

然后我们使用Clojure的解构迭代列表,以提取原始列表的元素。

通常,如果要使用要应用的函数的返回值,则需要map。如果您只是为其副作用执行函数,我通常使用doseqmap并行工作,doseq遍历列表的Cartesian Product,因此需要map和{{} 1}}以获得我们想要的行为。

答案 2 :(得分:0)

(doseq ... (map解决方案的替代方案,如果您想要成对迭代而不是笛卡尔积,您还可以将partitioninterleave合并为:

> (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调用提供(懒)seq对。