>需要你的帮助。坚持一个直观简单的任务。
我有几个向量的向量。每个子向量的第一个元素是一个数字键。所有父向量都按这些键排序。例如:
[[1 a b] [3 c d] [4 f d] .... ]
[[1 aa bb] [2 cc dd] [3 ww qq] [5 f]... ]
[[3 ccc ddd] [4 fff ddd] ...]
需要澄清嵌套向量中的某些键值可能缺失,但排序顺序有保证。
我需要通过数字键将所有这些向量合并到某个统一的结构中。我现在还需要,在原始矢量或矢量中缺少一个键。
喜欢这个:
[ [[1 a b][1 aa bb][]] [[][2 cc dd]] [[3 c d][3 ww qq][3 ccc ddd]] [[4 f d][][4 fff dd]]...]
您可以将问题分为两部分:
1) 按排序顺序获取唯一键
2) 对于每个唯一键,遍历向量列表,并输出键的条目,如果缺少,则输出空列表
要获取唯一键,只需将所有键拉到列表中,将它们连接成一个大列表,然后将它们放入排序集中:
(into
(sorted-set)
(apply concat
(for [vector vectors]
(map first vector))))
如果我们从以下向量列表开始:
(def vectors
[[[1 'a 'b] [3 'c 'd] [4 'f 'd]]
[[1 'aa 'bb] [2 'cc 'dd] [3 'ww 'qq] [5 'f]]
[[3 'ccc 'ddd] [4 'fff 'ddd]]])
然后我们得到一组排序的:
=> #{1 2 3 4 5}
目前为止,一切都好。 现在,对于该排序集中的每个键,我们需要遍历向量,并获取带有该键的条目,或者如果缺少空列表,则获取空列表。 您可以使用两个"for"表单,然后使用"some"来查找条目(如果存在)
(for [k #{1 2 3 4 5}]
(for [vector vectors]
(or (some #(when (= (first %) k) %) vector )
[])))
这会产生:
=> (([1 a b] [1 aa bb] []) ([] [2 cc dd] []) ([3 c d] [3 ww qq] [3 ccc ddd]) ([4 f d] [] [4 fff ddd]) ([] [5 f] []))
我认为这就是你想要的。 (如果您需要向量而不是列表,只需在适当的位置使用"(into [] ...)"。
综上所述,我们得到:
(defn unify-vectors [vectors]
(for [k (into (sorted-set)
(apply concat
(for [vector vectors]
(map first vector))))]
(for [vector vectors]
(or (some #(when (= (first %) k) %) vector)
[]))))
(unify-vectors
[[[1 'a 'b] [3 'c 'd] [4 'f 'd]]
[[1 'aa 'bb] [2 'cc 'dd] [3 'ww 'qq] [5 'f]]
[[3 'ccc 'ddd] [4 'fff 'ddd]]])
=> (([1 a b] [1 aa bb] []) ([] [2 cc dd] []) ([3 c d] [3 ww qq] [3 ccc ddd]) ([4 f d] [] [4 fff ddd]) ([] [5 f] []))
我没有一个完整的解决方案给你,但作为一个提示:使用group-by
对第一个参数的向量进行排序。
这将更加惯用,当它准备好时可能只有几行。
所以你可以写一些类似的东西
(group-by first [[1 :a :b] [3 :c :d] [4 :f :d]])
并对所有向量执行此操作。然后,您可以使用group-by
提供的键对它们进行排序/合并。
这是一个简单的解决方法,但不符合 Clojure 编程的最佳实践。只是在这里给出一个简单的想法。
(def vectors
[
[[1 'a 'b] [3 'c 'd] [4 'f 'd]]
[[1 'aa 'bb] [2 'cc 'dd] [3 'ww 'qq] [5 'f]]
[[3 'ccc 'ddd] [4 'fff 'ddd]]]
)
(loop [i 1
result []]
(def sub-result [])
(doseq [v vectors]
(doseq [sub-v v]
(if
(= i (first sub-v))
(def sub-result (into sub-result [sub-v]))))
(if-not
(some #{i}
(map first v))
(def sub-result (into sub-result [[]]))
))
(if (< i 6)
(recur (inc i) (into result [sub-result]))
(print result)))