Clojure:如何将向量的几个排序向量合并到公共结构中



>需要你的帮助。坚持一个直观简单的任务。

我有几个向量的向量。每个子向量的第一个元素是一个数字键。所有父向量都按这些键排序。例如:

[[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)))

最新更新