Clojure 如何将一个集合中的所有元素与另一个集合中的所有元素相乘?
假设我有:Clojure 如何将一个集合中的所有元素与另一个集合中的所有元素相乘?,clojure,Clojure,假设我有: (def s1 [1 2 3 4 5]) (def s2 [1 2 3 4 5]) 对于s1中的每个x,我想将其与s2中的每个y相乘 澄清一下,我基本上想要笛卡尔积,所以我认为map在这里不起作用。这里是java 1.5(或更新版本)与Michal代码的等价物: (for [x1 s1 x2 s2] (* x1 x2)) List<Integer> numbers = new ArrayList<Integer>(); for(
(def s1 [1 2 3 4 5])
(def s2 [1 2 3 4 5])
对于s1
中的每个x
,我想将其与s2
中的每个y
相乘
澄清一下,我基本上想要笛卡尔积,所以我认为
map
在这里不起作用。这里是java 1.5(或更新版本)与Michal代码的等价物:
(for [x1 s1
x2 s2]
(* x1 x2))
List<Integer> numbers = new ArrayList<Integer>();
for(int x1 : s1) {
for(int x2 : s2) {
numbers.add(x1 * x2);
}
}
List number=new ArrayList();
对于(int-x1:s1){
用于(整数x2:s2){
数字。加上(x1*x2);
}
}
区别在于java中的for
循环不像clojure中那样返回序列,因此需要使用可变数组列表来构造结果
肯定没有clojure版本漂亮,但比Java 1.4中的功能要好得多。一个简单、直观的演示for
的基本功能:
user=> (pprint
(for [tens (range 10)
ones (range 10)]
[tens ones]))
([0 0]
[0 1]
[0 2]
[0 3]
[0 4]
[0 5]
[0 6]
[0 7]
[0 8]
[0 9]
[1 0]
[1 1]
[1 2]
[1 3]
[1 4]
[1 5]
[1 6]
[1 7]
[1 8]
[1 9]
[2 0]
[2 1]
[2 2]
[2 3]
[2 4]
[2 5]
[2 6]
[2 7]
[2 8]
[2 9]
[3 0]
[3 1]
[3 2]
[3 3]
[3 4]
[3 5]
[3 6]
[3 7]
[3 8]
[3 9]
[4 0]
[4 1]
[4 2]
[4 3]
[4 4]
[4 5]
[4 6]
[4 7]
[4 8]
[4 9]
[5 0]
[5 1]
[5 2]
[5 3]
[5 4]
[5 5]
[5 6]
[5 7]
[5 8]
[5 9]
[6 0]
[6 1]
[6 2]
[6 3]
[6 4]
[6 5]
[6 6]
[6 7]
[6 8]
[6 9]
[7 0]
[7 1]
[7 2]
[7 3]
[7 4]
[7 5]
[7 6]
[7 7]
[7 8]
[7 9]
[8 0]
[8 1]
[8 2]
[8 3]
[8 4]
[8 5]
[8 6]
[8 7]
[8 8]
[8 9]
[9 0]
[9 1]
[9 2]
[9 3]
[9 4]
[9 5]
[9 6]
[9 7]
[9 8]
[9 9])
虽然使用for的解决方案更好,但如果您在理解for时遇到困难,这里有一个映射的唯一版本:
(map #(map (partial * %) s2) s1)
上述的扩展为类似的内容,只是它将使用另一个匿名函数而不是部分,类似如下:
(map (fn [x] (map (fn [y] (* x y)) s2)) s1)
或者,格式整齐:
(map
(fn [x]
(map
(fn [y]
(* x y))
s2))
s1)
尽可能简单:
(map * '(1 2) '(3 4))
将产生:
(3 8)
是。。。美丽的。我对Clojure和函数式编程非常陌生,尽管我知道它的用途。。。我仍然觉得很尴尬,很难把头绕过去。你能描述一下那里发生了什么吗?首先,你可以在Clojure REPL中键入(doc for)
,以便(希望)很好地描述for
的功能;如果您发现它没有达到您的期望,那么您的经验将有助于改进docstring!其次,这里有一个简短的总结:for
采用绑定向量和单个“body”表达式。绑定向量包括局部变量的名称(x1
和x2
)和序列生成表达式(s1
和s2
)。对于seqs的笛卡尔乘积中的每个元组(这里是s1
和s2
的乘积中的每个(x1
,x2
),主体都会被评估一次。幸运的是,我确实在线阅读了for函数的文档,不幸的是它让我的大脑爆炸。请参阅我的java等价答案。希望它能帮助你理解。只是为了好玩,这里有一些其他语言的解决方案。Erlang(以及任何其他具有列表理解功能的语言):[X*Y | | X顺便说一句,要获得与第一个(外部)映射相同的行为,应将其替换为mapcat。@Blaine自己看:-):(使用“clojure.pprint”(设置pprint分派代码分派)(pprint(macroexpand)(用于[x1 s1 x2 x2](*x1 x2)))我无法理解评论回复中的格式,但你可以这样做:(时间(dotimes[#1e8](对于[x1(范围100)x2(范围100)](*x1-x2)))
“经过的时间:1280.237268毫秒”(时间(dotimes[#1e8](映射)(部分*)(范围100))(范围100)))
“经过的时间:1743.519268毫秒”嗯……不完全是我想要的。它符合我的英语描述,但我应该从一开始就说我在寻找两个集合的笛卡尔积。我只是不知道它叫什么。哦,事实上,我应该更仔细地准备答案。但仍然..clojure;)