【问题标题】:intersection between two maps in clojureclojure中两个地图之间的交集
【发布时间】:2017-03-07 03:20:44
【问题描述】:

我有哈希映射,我正在尝试获取键之间的交集。但是函数“intersection”只适用于集合。

所以我得到了键,将键转换为集合,然后调用交叉点,如下所示:

(intersection (set (keys map-1)) (set (keys map-2)))

有更好的方法吗?

谢谢

【问题讨论】:

  • 那是惯用的 Clojure

标签: clojure functional-programming


【解决方案1】:

这可能是最直接/最简洁的方法,并且不需要构建任何集合(相对昂贵)。

(keys (select-keys map-1 (keys map-2)))

终于来了一个优化的版本,速度快一点,阅读难度也大一点:

(keep #(some->> % (find map-1) key) (keys map-2))

【讨论】:

  • 几件事。 1)问题暗示intersection,它返回一个集合。您的两个解决方案都返回序列。 2) IMO,keys 应该返回一个clojure.lang.MapKeys,一个通过忽略其值伪装成集合的地图。它不存在。我应该写它。
  • 很好,非常感谢。有没有办法做相反的事情?取而代之的是交叉口,得到区别?我尝试了“差异”功能,但它仍然需要一个集合作为第一个参数。 (difference (set (keys map-2)) (keys map-1))
  • (keys (apply dissoc map-1 (keys map-2))) 应该可以解决问题
  • 如果 map-1 的键比 map-2 少(如果有任何机会您可以事先确定,这是一个潜在的优化),这将是最好的选择
【解决方案2】:

您的解决方案清晰简洁。

如果关注性能,可以通过模仿clojure.set/intersection的结构来避免构造中间集:

(defn key-intersection [s1 s2]
  (if (< (count s2) (count s1))
    (recur s2 s1)
    (reduce
     (fn [result item]
       (if (contains? s2 item)
         (conj result item)
         result))
     #{}
     (keys s1))))

【讨论】:

  • 因为我们都提到了性能,criterium 说我的版本在 10 和 1000 元素地图上比你的版本略快,而在 100 元素地图上略慢。两者都比原来列出的速度快约 3 倍。
  • 10 个元素:11.5 / 2.78 / 3.15; 100 个元素:117 / 27.3 / 27.0; 1000 个元素 1540 / 301 / 315
  • 使用我的优化版本,我得到 2.81; 26.8; 285
  • @noisesmith 很有趣。我很惊讶差异没有更大,因为我在您的第一个版本使用循环的引擎盖下使用reduce。我在你的回答中留下了几个 cmets:我比我更喜欢它,并投票给它:)。
【解决方案3】:

以下内容应该适用于任意数量的地图

(defn key-intersection [m & ms]
  (reduce #(keys (select-keys %2 %1)) (keys m) ms))

(defn key-intersection [m & ms]
  (reduce (fn [v c] (keep #(some->> % (find c) key) v)) (keys m) ms))

【讨论】:

    猜你喜欢
    • 2016-01-20
    • 2015-04-14
    • 2018-06-22
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    相关资源
    最近更新 更多