Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 如何将一个集合中的所有元素与另一个集合中的所有元素相乘?_Clojure - Fatal编程技术网

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