Clojure排序映射:找到小于或等于x(地板键)的最大键

Lin*_*don 5 java functional-programming clojure data-structures

我有一个问题,我有一些代表时间的键和每次的一些值。一个小例子:

 (sorted-map -4 "a" -1 "b" 2 "c" 3 "d")
Run Code Online (Sandbox Code Playgroud)

对于给定的 x,我想找到小于或等于 x 的最大键。

例如,在 Julia DataStructures 包中,有一个排序字典,其方法如下

searchsortedlast(sc,k) 参数 sc 是 SortedDict、SortedMultiDict 或 SortedSet,k 是键。此例程返回容器中键小于或等于 k ​​的最后一项的半标记。如果没有这样的键,则返回启动前的半令牌。时间:O(c log n)

我一直在尝试在 clojure 中查找有关类似功能的文档,但没有找到任何内容。我的天真的做法如下:

(apply max (filter #(< % x) (keys (sorted-map -4 "a" -1 "b" 2 "c" 3 "d" -10 "e"))))

但我认为这是次优的,因为它首先收集所有密钥,然后过滤它们,从而创建不必要的计算。

我的问题是 1)是否已经有一个我找不到的实现此功能的函数。2) 如果不是这种情况,我应该搜索 Java 数据结构并使用 java 数据结构和关联方法 3) 是否可以使我的方法变得懒惰,以便更有效?

编辑:

来自 Java 的 TreeMap:

K FloorKey(K key) 返回小于或等于给定键的最大键,如果没有这样的键,则返回 null。

这就是我正在用 clojure 排序映射寻找的东西。我应该放弃排序映射并使用 Javas 树形图吗?

编辑2:

我发现这个 https://github.com/clojure/data.avl 它提供了带有“最近键”函数的替代排序映射实现

Pio*_*dyl 4

要使用排序的集合(例如排序的地图),您可以使用subseqrsubseq

在您的示例中,要查找最大键等于或小于的条目,x可以使用:

(let [m (sorted-map -4 "a" -1 "b" 2 "c" 3 "d")
      x 0]
  (first (rsubseq m <= x)))
;; => [-1 "b"]
Run Code Online (Sandbox Code Playgroud)

  • 对“sorted-seq”中元素的访问是 log n (http://clojure.org/reference/data_structs#Maps)。实际上它们是“PersistentTreeMap”的底层(https://github.com/clojure/clojure/blob/clojure-1.8.0/src/clj/clojure/core.clj#L398)。`subseq` 和 `rsubseq` 分别作为 `&gt;`/`&gt;=` 和 `&lt;`/`&lt;=` 原始集合的“视图”来实现,或者作为其他测试函数的 `take-while` 来实现。 (2认同)