【问题标题】:Finding keys closest to a given value for clojure sorted-maps为 clojure 排序映射查找最接近给定值的键
【发布时间】:2009-12-30 19:06:59
【问题描述】:

对于 clojure 的 sorted-map,我如何找到键最接近给定值的条目?

例如假设我有

(def my-map (sorted-map 
                      1 A 
                      2 B
                      5 C))

我想要一个类似的功能

(find-closest my-map 4)

将返回 (5,C),因为这是具有最接近键的条目。我可以进行线性搜索,但由于地图已排序,因此应该有一种方法可以在 O(log n) 之类的内容中找到该值。

我在 API 中找不到任何使这成为可能的东西。例如,如果我可以要求地图中的第 i 个条目,我可以拼凑出一个我想要的函数,但我找不到任何这样的函数。

编辑:

显然 sorted-map 是基于一个用 java 实现的 PersistentTreeMap 类,它是一棵红黑树。所以这看起来应该是可行的,至少在原则上是这样。

【问题讨论】:

    标签: data-structures clojure


    【解决方案1】:

    subseq 和 rsubseq 非常快,因为它们利用了树结构:

    (def m (sorted-map 1 :a, 2 :b, 5 :c)) 
    
    (defn abs [x] (if (neg? x) (- x) x))
    (defn find-closest [sm k]
      (if-let [a (key (first (rsubseq sm <= k)))]
        (if (= a k)
          a
          (if-let [b (key (first (subseq sm >= k)))]
            (if (< (abs (- k b)) (abs (- k a)))
              b
              a)))
        (key (first (subseq sm >= k)))))
    
    user=> (find-closest m 4)
    5
    user=> (find-closest m 3)
    2
    

    这比理想的工作稍微多一点,在理想的情况下,我们只需进行

    【讨论】:

      【解决方案2】:

      使用 Clojure 贡献库 data.avl。它支持具有最近函数和其他有用功能的排序地图。

      https://github.com/clojure/data.avl

      【讨论】:

        【解决方案3】:

        我想到的第一件事是将地图的键拉出到一个向量中,然后在其中进行二进制搜索。如果没有与您的键完全匹配,则二进制搜索中涉及的两个指针最终将指向它两侧的两个元素,然后您可以在单个(可能是平局)操作中选择更接近的一个。

        【讨论】:

        • 由于地图已经排序,我(希望)不必将所有键都拉出地图。
        • 同意;但我没有看到任何其他方式来获得对密钥的随机访问。如果您进行顺序搜索,平均而言,您需要比较 50% 的键,而我的解决方案需要复制 100% - 这太可怕了 - 然后是 log2(n) 搜索。我的解决方案只有在您对同一数据进行多次此类搜索时才有效。也许更聪明的人会出现并发布一个让我们所有人惊叹的解决方案。
        猜你喜欢
        • 1970-01-01
        • 2022-07-29
        • 1970-01-01
        • 2015-07-26
        • 1970-01-01
        • 2017-09-20
        • 2011-10-25
        • 2015-04-24
        • 1970-01-01
        相关资源
        最近更新 更多