以下是这种情况:我有一个向量向量(“数据”),一组标题,一个标题子集(“主标题”),一个常量(“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)
答案 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
的每个元素。
上次我错过了添加常量的部分。所以,为了做到这一点,我们需要改变一些代码。让我们更改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)))
我更改了应用mmap
和permutate
函数的顺序,因为您似乎不想将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]]