Clojure重排和矢量矢量的映射

时间:2014-04-10 19:45:45

标签: vector clojure

以下是这种情况:我有一个向量向量(“数据”),一组标题,一个标题子集(“主标题”),一个常量(“C”),一个元素方面的函数( “f”)和剩余的标题(“二级标题”)。我的目标是获取“数据”并生成一个新的向量向量。

示例数据:

[[1.0 "A" 2.0]
[1.0 "B" 4.0]]

示例标题:

["o1" "i1" "i2"]

示例主标题:

 ["i1" "i2"]

示例辅助标头:

 ["o1"]

矢量的新矢量示例:

[[(f "A") (f 2.0) C (f 1.0)]
[(f "B") (f 4.0) C (f 1.0)]]

我目前的尝试是mapv每一行,然后使用if映射索引每个元素以检查主成员资格,然后是常量,然后使用if映射索引每个元素以检查辅助成员资格,最后是结果。但我没有让它正常工作。

示例代码:

(mapv (fn [row] (conj (vec (flatten (map-indexed
                                    (fn [idx item] (let [header-name (nth headers idx)] 
                                                        (if (= (some #{header-name} primary-headers) headers-name) (f item))))
                                    row)))

                  C
                  (vec (flatten (map-indexed
                                    (fn [idx item] (let [header-name (nth headers idx)] 
                                                        (if (= (some #{header-name} secondary-headers) headers-name) (f item))))
                                    row)))))
 data)

3 个答案:

答案 0 :(得分:2)

你应该考虑使用core.matrix这样的东西。它是Clojure中用于多维数组编程的非常灵活的工具。

大多数阵列操作操作可能是1-2个衬垫.....

(def DATA [[1.0 "A" 2.0]
           [1.0 "B" 4.0]])

(emap (partial str "f:") (transpose (mapv #(get-column DATA %) [1 0 2])))
=> [["f:A" "f:1.0" "f:2.0"] 
    ["f:B" "f:1.0" "f:4.0"]]

您可能需要查找列名来计算[1 0 2]向量,但希望这可以让您知道如何执行此操作....

答案 1 :(得分:1)

不确定我的问题是否正确,但看起来你想要这样的事情:

(defn magic [data h p s f]
  (let [idx (map (into {} (map-indexed #(vector %2 %1) h))
                 (concat p s))]
    (mapv #(mapv (comp f (partial get %))
                 idx)
          data)))

以下是我的magic功能的示例:

(magic [[1.0 "A" 2.0]
        [1.0 "B" 4.0]]
       ["o1" "i1" "i2"]
       ["i1" "i2"]
       ["o1"]
       #(str "<" % ">"))

[["<A>" "<2.0>" "<1.0>"]
 ["<B>" "<4.0>" "<1.0>"]]

让我们仔细看看它。

首先,我正在计算排列索引idx。在你的情况下它是(1 2 0)。为了计算它,我将["o1" "i1" "i2"]转换为哈希映射{"o1" 0, "i1" 1, "i2" 2},然后在("i1" "i2" "o1")主要和次要标题序列上使用它。

然后我使用idx重新排列data矩阵。在这一步中,我还将f函数应用于新重新排列的矩阵的每个元素。

更新

我认为将复杂的magic函数拆分为三个更简单的函数是最好的:

(defn getPermutation [h1 h2]
  (map (into {} (map-indexed #(vector %2 %1) h1))
       h2))

(defn permutate [idx data]
  (mapv #(mapv (partial get %) idx)
        data)))

(defn mmap [f data]
  (mapv (partial mapv f)
        data))

这里的每个函数都是原子的(即执行单个任务),并且它们都可以轻松组合以完成magic函数所做的事情:

(defn magic [data h p s f]
  (let [idx (getPermutation h (concat p s))]
    (->> data
         (permutate idx)
         (mmap f))))
这里的

getPermutation函数计算idx置换索引向量。

permutate根据给定的data向量重新排列矩阵idx的列。

mmap将函数f应用于矩阵data的每个元素。

更新2

上次我错过了添加常量的部分。所以,为了做到这一点,我们需要改变一些代码。让我们更改permutate函数,允许它向矩阵插入新值。

(defn permutate [idx data & [default-val]]
  (mapv #(mapv (partial get %) idx (repeat default-val))
        data)))

现在,如果它无法获取具有指定索引default-val的元素,它将使用idx

我们还需要一个新的magic函数:

(defn magic2 [data h p s f c]
  (let [idx (getPermutation h (concat p [nil] s))]
    (permutate idx (mmap f data) c)))

我更改了应用mmappermutate函数的顺序,因为您似乎不想将f应用于常量。

它有效:

(magic2 [[1.0 "A" 2.0]
         [1.0 "B" 4.0]]
        ["o1" "i1" "i2"]
        ["i1" "i2"]
        ["o1"]
        #(str "<" % ">")
        "-->")

[["<A>" "<2.0>" "-->" "<1.0>"]
 ["<B>" "<4.0>" "-->" "<1.0>"]]

答案 2 :(得分:1)

鉴于

(def data [[1.0 "A" 2.0] [1.0 "B" 4.0]])
(def headers ["o1" "i1" "i2"])
(def primaries ["i1" "i2"])
(def secondaries ["o1"])

(defn invert-sequence [s] (into {} (map-indexed (fn [i x] [x i]) s)))

......这就是工作:

(defn produce [hs ps ss f data const]
  (let [perms (map #(mapv (invert-sequence hs) %) [ps ss])]
    (mapv (fn [v] (->> perms
                       (map #(map (comp f v) %))
                       (interpose [const])
                       (apply concat)
                       vec))
          data)))

使用问题中的示例:

(produce headers primaries secondaries #(list 'f %) data 'C)
; [[(f "A") (f 2.0) C (f 1.0)] [(f "B") (f 4.0) C (f 1.0)]]

使用Leonid Beschastny的例子:

(produce headers primaries secondaries #(str "<" % ">") data 'C)
; [["<A>" "<2.0>" C "<1.0>"] ["<B>" "<4.0>" C "<1.0>"]]

使用str

(produce headers primaries secondaries str data 'C)
; [["A" "2.0" C "1.0"] ["B" "4.0" C "1.0"]]

使用identity

(produce headers primaries secondaries identity data 'C)
; [["A" 2.0 C 1.0] ["B" 4.0 C 1.0]]
相关问题