将向量元素与相应列表交织以创建向量的新向量

时间:2014-04-03 03:47:42

标签: list vector clojure

我的数据格式如下:

[["i1" "i2"]
 ['("A" "B" "C" "D") '("red" "blue" "green" "yellow")]]

我想转换它以获得新的数据结构:

[["column" "value"]
 ["i1" "A"]
 ["i1" "B"]
 ["i1" "C"]
 ["i1" "D"]
 ["i2" "red"]
 ["i2" "blue"]
 ["i2" "green"]
 ["i2" "yellow"]]

对这个棘手问题的任何帮助都会很棒。

我的尝试远远涉及使用嵌套" for"语句,但我不能得到与标题向量相同级别的结果向量,尽管许多尝试转换结果。我也用过" interleave"并且"重复"列的值,但也会在错误的级别创建列表。

5 个答案:

答案 0 :(得分:2)

(defn doit [[is vss]]
  (vec (cons
         ["column" "value"]
         (mapcat (fn [i vs] (mapv (fn [v] [i v]) vs)) is vss))))

答案 1 :(得分:2)

(defn convert
  [[header data]]
  (->> (mapcat #(map vector (repeat %) %2) header data)
       (cons ["column" "value"])))

(convert '[["i1" "i2"] [("A" "B" "C" "D") ("red" "blue" "green" "yellow")]])
;; => (["column" "value"] 
;;     ["i1" "A"] ["i1" "B"] ["i1" "C"] ["i1" "D"] 
;;     ["i2" "red"] ["i2" "blue"] ["i2" "green"] ["i2" "yellow"])

答案 2 :(得分:1)

(defn conform
  [[ks & rows]]
  (mapcat
   (fn [row]
     (mapcat (fn [k val]
               (map (partial vector k) val))
             ks row))
   rows))

你的例子:

(conform [["i1" "i2"] ['("A" "B" "C" "D") '("red" "blue" "green" "yellow")]])
=> (["i1" "A"] ["i1" "B"] ["i1" "C"] ["i1" "D"]
    ["i2" "red"] ["i2" "blue"] ["i2" "green"] ["i2" "yellow"])

加成:

(conform [["i1" "i2"]
          ['("A" "B" "C" "D") '("red" "blue" "green" "yellow")]
          ['("E" "F" "G" "H") '("Mara" "Lara" "Clara" "Foxy")]])

=> (["i1" "A"] ["i1" "B"] ["i1" "C"] ["i1" "D"] 
    ["i2" "red"] ["i2" "blue"] ["i2" "green"] ["i2" "yellow"] 
    ["i1" "E"] ["i1" "F"] ["i1" "G"] ["i1" "H"] 
    ["i2" "Mara"] ["i2" "Lara"] ["i2" "Clara"] ["i2" "Foxy"])

更多奖金:

(conform [["i1" "i2" "i3"]
          ['("A" "B" "C" "D") '("red" "blue" "green" "yellow") ["Ufo"]]
          ['("E" "F" "G" "H") '("Mara" "Lara" "Clara" "Foxy") ["Orange" "Apple"]]])

=> (["i1" "A"] ["i1" "B"] ["i1" "C"] ["i1" "D"] 
    ["i2" "red"] ["i2" "blue"] ["i2" "green"] ["i2" "yellow"] 
    ["i3" "Ufo"] 
    ["i1" "E"] ["i1" "F"] ["i1" "G"] ["i1" "H"] 
    ["i2" "Mara"] ["i2" "Lara"] ["i2" "Clara"] ["i2" "Foxy"] ["i3" "Orange"] ["i3" "Apple"])

从结果中创建地图很简单:

(reduce (fn [acc [k v]]
          (update-in acc [k] (fnil conj []) v)) {} *1 )

=> {"i3" ["Ufo" "Orange" "Apple"], 
    "i2" ["red" "blue" "green" "yellow" "Mara" "Lara" "Clara" "Foxy"], 
    "i1" ["A" "B" "C" "D" "E" "F" "G" "H"]}

答案 3 :(得分:0)

不是惯用语,但是做了伎俩。

((fn [coll]
   (let [ks (first coll) vs (last coll)]
     (cons 
      '("column" "value")
      (partition 2 (concat
                    (interleave (repeat (first ks)) (first vs))
                    (interleave (repeat (last ks)) (last vs)))))))
 [["i1" "i2"]
  ['("A" "B" "C" "D") '("red" "blue" "green" "yellow")]])

答案 4 :(得分:0)

这里有一些有趣的答案。我将在概念上添加它,我认为这是for的好地方。对于第一个向量中的每个项目,您希望将其与第二个向量中相应列表中的项目配对。

(defn convert [[cols vals]]
    (vec (cons ["column" "value"] ;; turn the list into a vector.
            (for [i (range (count cols)) ;; i <- index over columns
                  j (nth vals i)] ;; j <- items from the ith list
              [(nth cols i) j])))) ;; [col val]

user=>(convert data)

这很容易修改,以处理更多的值向量:

(defn convert [[cols & vals]]
    (cons ["column" "value"]
        (mapcat #(for [i (range (count cols))
                       j (nth % i)]
                   [(nth cols i) j])
                vals)))