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

时间:2014-03-06 08:15:10

标签: 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]]...]

3 个答案:

答案 0 :(得分:2)

我没有完整的解决方案,但作为提示:使用group-by为第一个参数排序向量。

这将更加惯用,并且在准备就绪时可能只有几行。

所以你可以写点像

(group-by first [[1 :a :b] [3 :c :d] [4 :f :d]])

并为所有向量执行此操作。然后,您可以使用group-by提供的密钥对它们进行排序/合并。

答案 1 :(得分:2)

您可以将问题分解为两部分:

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

我认为这就是你想要的。 (如果你需要向量而不是列表,只需在适当的位置使用“(进入[] ...)”。)

总而言之,我们得到:

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

答案 2 :(得分:1)

这是一个简单的解决方法,但不符合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)))