【问题标题】:How do I multiply all elements in one collection with all the elements in another collection?如何将一个集合中的所有元素与另一个集合中的所有元素相乘?
【发布时间】:2010-07-23 21:32:57
【问题描述】:

说我有:

(def s1 [1 2 3 4 5])
(def s2 [1 2 3 4 5])

对于s1 中的每个x,我想将它与s2 中的每个y 相乘。


澄清一下,我基本上想要笛卡尔积,所以我不认为map 在这里工作。

【问题讨论】:

  • 只是为了好玩,这里有一些其他语言的解决方案。 Erlang(以及任何其他具有列表理解的语言):[X * Y || X <- S1, Y <- S2] Ruby (1.8.7+):s1.product(s2).map {|x,y| x*y}

标签: clojure


【解决方案1】:
(for [x1 s1
      x2 s2]
  (* x1 x2))

【讨论】:

  • 它...很漂亮。 流泪
  • 我对 Clojure 和一般的函数式编程非常陌生,尽管我知道它是做什么的……我仍然觉得很尴尬,很难把它包起来。你能描述一下那里发生了什么吗?
  • 首先,您可以在 Clojure REPL 中键入 (doc for) 以获得(希望)对 for 所做工作的良好描述;如果您发现它没有达到您的期望,您的经验可以帮助改进文档字符串!其次,这里有一个简短的总结:for 接受一个绑定向量和一个单一的“body”表达式。绑定向量包括本地名称(上面的x1x2)和产生序列的表达式(s1s2)。对于 seq 的笛卡尔积中的每个项目元组(这里是 s1s2 的积中的每个(x1x2)),对主体进行一次评估。
  • 幸运的是,我确实在网上阅读了 for 函数的文档,不幸的是它让我的大脑爆炸了。
  • 查看我对 java 等价物的回答。希望它可以帮助您理解。
【解决方案2】:

虽然使用 for 的解决方案更好,但如果您在理解 for 时遇到困难,这里有一个仅适用于 ma​​p 的版本:

(map #(map (partial * %) s2) s1)
上面的

for 扩展为类似的东西,只是它会使用另一个匿名函数而不是 partial,如下所示:

(map (fn [x] (map (fn [y] (* x y)) s2)) s1)

或者,格式整齐:

(map
  (fn [x]
    (map
      (fn [y]
        (* x y))
      s2))
  s1)

【讨论】:

  • 顺便说一句,要获得与 for 相同的行为,应将第一个(外部)地图替换为 mapcat。
  • @Blaine 自己看看 :-) : (use 'clojure.pprint) (set-pprint-dispatch code-dispatch) (pprint (macroexpand '(for [x1 s1 x2 s2] (* x1 x2))))
  • 我无法弄清楚评论回复中的格式,但你去吧:(time (dotimes [_ 1e8] (for [ x1 (range 100) x2 (range 100)] (* x1 x2)) ))“经过的时间:1280.237268 毫秒”(time (dotimes [_ 1e8] (map #(map (partial * %) (range 100)) (range 100) ) ))“经过的时间:1743.519268 毫秒”
【解决方案3】:

这是与 Michal 的代码等效的 java 1.5(或更高版本):

List<Integer> numbers = new ArrayList<Integer>();    

for(int x1 : s1) {
  for(int x2 : s2) {
    numbers.add(x1 * x2);
  }
}

不同之处在于java中的for循环不会像在clojure中那样返回一个序列,所以你需要使用一个可变的ArrayList来构造结果。

绝对不如 clojure 版本漂亮,但比您在 Java 1.4 中必须做的要好得多。

【讨论】:

  • 但仍然..clojure ;)
【解决方案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])

【讨论】:

    【解决方案5】:

    尽可能简单:

    (map * '(1 2) '(3 4))
    

    将产生:

    (3 8)
    

    【讨论】:

    • 嗯...不是我想要的。它符合我的英文描述,但我应该从一开始就说我正在寻找两组的笛卡尔积。我只是不知道它叫什么。
    • 糟糕,确实,我应该更仔细地准备答案。
    猜你喜欢
    • 2022-01-18
    • 2012-12-12
    • 2021-12-08
    • 1970-01-01
    • 2012-10-31
    • 2017-05-02
    • 2011-05-23
    • 2013-01-10
    • 2013-05-28
    相关资源
    最近更新 更多