首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用树状图作为二维键?

如何使用树状图作为二维键?
EN

Stack Overflow用户
提问于 2015-10-02 09:02:00
回答 2查看 85关注 0票数 0

我想绘制大量的元组图。我的地图看起来像:

代码语言:javascript
运行
复制
{[1 2] :thing}

但可能有几百万人。我有一种感觉,一张树图可能是一个好东西来测试,所以我正在努力使它发挥作用。不过,我似乎不能正确地理解比较功能。

代码语言:javascript
运行
复制
(defn compare 
  [[x y] [xx yy]]
  (cond
   (and (= x xx) (= y yy)) 0
   (and (<= x xx) (<= y yy)) -1
   (and (<= x xx) (> y yy)) -1
   (and (> x xx) (<= y yy)) 1
   (and (> x xx) (> y yy)) 1))

一些琐碎的输入似乎有效。

代码语言:javascript
运行
复制
user=> (compare [1 1] [1 1])
0
user=> (compare [1 1] [2 2])
-1
user=> (compare [1 2] [2 1])
-1
user=> (compare [2 1] [1 2])
1

但是如果我创建包含所有组合的输入,地图应该考虑它们的不同。

代码语言:javascript
运行
复制
(def inputs
    "All tuples of [0-4, 5-10]."
    (clojure.math.combinatorics/cartesian-product
      (range 0 4) 
      (range 5 10)))

(def input-pairs
     "All possible pairs of tuples"
     (clojure.math.combinatorics/cartesian-product inputs inputs))

如果我测试比较函数,只有当两个向量在结构上相同时,它才返回零。

代码语言:javascript
运行
复制
user=> (doseq [[a b] input-pairs]
  #_=>   (when (zero? (compare a b)) (prn a b)))
(0 5) (0 5)
(0 6) (0 6)
(0 7) (0 7)
(0 8) (0 8)
(0 9) (0 9)
(1 5) (1 5)
etc

所以我认为我的比较函数是正确的。然而,在树状图中使用它会产生一些奇怪的结果:

代码语言:javascript
运行
复制
(def inputs-kvs
    "Inputs in the format that the hash-map and sorted-map constructor understand"
    (mapcat #(vector % (apply str %))
            (clojure.math.combinatorics/cartesian-product
              (range 0 4) 
              (range 5 10))))

把这些放在hashmap中会给出正确的答案。

代码语言:javascript
运行
复制
(count (apply assoc (hash-map) inputs-kvs))
=> 20

但是把它们放在树状图上,用给定的比较:

代码语言:javascript
运行
复制
(def structure (sorted-map-by compare))
(count (apply assoc structure inputs-kvs))
=> 4

(apply assoc structure inputs-kvs)
=> {(0 5) "25", (1 6) "36", (2 7) "37", (3 5) "39"}

"25“已存储在(0 5)插槽中。但是,比较函数并不表示(0 5)(2 5)是相同的:

代码语言:javascript
运行
复制
=> (compare [0 5] [2 5])
-1

我做错了什么?我能让这件事成功吗?把二维空间投射到一维空间上有意义吗?

(为了避免你有一个问题,是的,我尝试过一种二维结构,例如(sorted-map 1 (sorted-map 2 :value)),但我正在努力寻找性能更好的替代方案)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-10-02 11:49:07

Clojure已经提供了它自己的compare

代码语言:javascript
运行
复制
user=> (doc compare)
-------------------------
clojure.core/compare
([x y])
  Comparator. Returns a negative number, zero, or a positive number
  when x is logically 'less than', 'equal to', or 'greater than'
  y. Same as Java x.compareTo(y) except it also works for nil, and
  compares numbers and collections in a type-independent manner. x
  must implement Comparable

它的行为与OPs自己的函数相同,但最有可能是更高效的:

代码语言:javascript
运行
复制
user=> (compare [1 1] [1 1])
0
user=> (compare [1 1] [2 2])
-1
user=> (compare [2 1] [1 2])
1

这种行为记录在有关数据结构文档中的向量(IPersistentVector)的部分中。

首先按长度比较向量,然后按顺序对每个元素进行比较。

因此,您可以只从核心使用sorted-map-by compare,或者因为这是默认的,所以数据结构的sorted-map是默认的:

代码语言:javascript
运行
复制
user=> (def m (into {} (let [r #(- (rand-int 10) (rand-int 10))] (for [a (range -1 2) b (range -1 2)] [[(r) (r)] (str a b)]))))
#'user/m
user=> (>pprint m)
{[-7 -4] "10",
 [-3 5] "01",
 [-5 -7] "00",
 [5 2] "11",
 [-3 1] "-10",
 [7 -4] "-11",
 [0 -6] "0-1",
 [3 1] "-1-1",
 [-8 -1] "1-1"}
nil
user=> (>pprint (into (sorted-map-by compare) m))
{[-8 -1] "1-1",
 [-7 -4] "10",
 [-5 -7] "00",
 [-3 1] "-10",
 [-3 5] "01",
 [0 -6] "0-1",
 [3 1] "-1-1",
 [5 2] "11",
 [7 -4] "-11"}
nil
user=> (>pprint (into (sorted-map) m))
{[-8 -1] "1-1",
 [-7 -4] "10",
 [-5 -7] "00",
 [-3 1] "-10",
 [-3 5] "01",
 [0 -6] "0-1",
 [3 1] "-1-1",
 [5 2] "11",
 [7 -4] "-11"}
nil
user=> (assert (= (into (sorted-map-by compare) m) (into (sorted-map) m)))
nil
票数 2
EN

Stack Overflow用户

发布于 2015-10-02 10:53:36

我只是添加了(vec %)来保持元组向量--不应该改变任何东西。

正如你所看到的,它在这里起作用。

可能你有一些旧的REPL的东西,尤其是自从你化名为clojure.core/compare之后?

代码语言:javascript
运行
复制
; using your compare function
(def inp (mapcat #(vector (vec %) (apply str %)) 
  (clojure.math.combinatorics/cartesian-product (range 0 4) (range 5 10))))
; => ([0 5] "05" [0 6] "06" [0 7] "07" [0 8] "08" ...
(count inp) 
; => 40 
(apply assoc structure inp)
; => {[0 9] "09", [0 8] "08", [0 7] "07", [0 6] "06", ....
(count (apply assoc structure inp))
; => 20
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32903820

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档