将包含可能为空的基元数组的嵌套数据结构与clojure.data/diff进行比较

时间:2015-10-13 12:04:55

标签: arrays clojure clojure-java-interop

我正在使用clojure.data/diff比较单元测试中的嵌套数据结构。它工作正常,直到遇到它(IMO)遇到空基元数组时行为不一致的问题。

非空基元数组与包含相同类型对象(例如双精度数)的向量相比较。但是,空原始数组不会比较相等(在diff函数的意义上)与空向量甚至是同一类型的另一个空数组。

这是一个显示我的问题的repl会话。我添加了一些评论。

nerom.nsd.dbserver=> (require '[clojure.data :as cd])
nil
;; this is as I would expect - a vector and a primitive array with 
;; same contents compare equal
nerom.nsd.dbserver=> (cd/diff [[1.1 2.2]] [(double-array [1.1 2.2])])
[nil nil [[1.1 2.2]]]
;; this is inconsistent with the previous - empty double array does 
;; not compare equal to an empty vector
nerom.nsd.dbserver=> (cd/diff [[]] [(double-array [])])
[[nil] [nil] nil]
;; two double arrays with the same contents compare equal
nerom.nsd.dbserver=> (cd/diff [(double-array [1.1 2.2])] [(double-array [1.1 2.2])])
[nil nil [[1.1 2.2]]]
;; except when they are empty, which is IMO inconsistent
nerom.nsd.dbserver=> (cd/diff [(double-array [])] [(double-array [])])
[[nil] [nil] nil]

如何使空数组比较空矢量或至少是相同类型的空矢量?

1 个答案:

答案 0 :(得分:2)

我想我找到了一个线索:

如果你看一下diff来源,你会看到以下内容:

(if (= a b)
    [nil nil a]
    (if (= (equality-partition a) (equality-partition b))
      (diff-similar a b)
      (atom-diff a b)))

首先将两个值与equality-partition进行比较,EqualityPartition在协议(require '[clojure.data :as d]) 中定义,返回一些关键字相等等级

因此,如果将此协议扩展到原始数组,则不会将它们视为相等:

user> (d/diff [(double-array [])] [(int-array [])])
[[nil] [nil] nil]

之前:

(extend-protocol d/EqualityPartition
  (Class/forName "[D")
  (equality-partition [_] :double-array))

(extend-protocol d/EqualityPartition
  (Class/forName "[I")
  (equality-partition [_] :int-array))

user> (d/equality-partition (double-array []))
:double-array
user> (d/equality-partition (int-array []))
:int-array

然后你扩展协议:

user> (d/diff [(double-array [])] [(int-array [])])
[[#object["[D" 0x1e2f0f97 "[D@1e2f0f97"]] [#object["[I" 0x207c60b5 "[I@207c60b5"]] nil]

后:

user> (d/diff [(double-array [])] [(double-array [])])
[[nil] [nil] nil]

user> (d/diff [(double-array [1])] [(double-array [10])])
[[[1.0]] [[10.0]] nil]

而类似类型的数组将像以前一样进行比较

clojure.data

进一步朝这个方向看:你可以调整扩展这个协议的比较(以及public static void main(String[] args) { String testValue="5006,3030,8080-8083"; Integer[]result=parseElements(testValue); for (Integer i:result){ System.out.println(i); } } /** * NumberList is a string of comma-separated elements that are either integers, or a range of integers of the form a-b. * @param numberList * @return all the integers in the list, and in ranges in the list, in a sorted list */ private static Integer[] parseElements(String integerList) { ArrayList<Integer> integers=new ArrayList<Integer>(); String[] csvs=integerList.split(","); for(String csv : csvs){ if(csv.contains("-")){ String[] range=csv.split("-"); Integer left=Integer.decode(range[0]); Integer right=Integer.decode(range[1]); for(Integer i=left;i<=right;i++){ integers.add(i); } } else { integers.add(Integer.decode(csv)); } } Collections.sort(integers); return integers.toArray(new Integer[0]); } 的其他协议)