如何将向量[1 2 3:a:b:c:A:B:C]转换为[{:index 1:lower:a:upper:A} {:index 2:lower:b:upper:B} { :index 3:lower:c:upper:C}]?

时间:2019-04-11 06:13:03

标签: clojure

我想知道如何转换

vector [1 2 3 :a :b :c :A :B :C] 

[ {:index 1 :lower :a :upper :A} {:index 2 :lower :b :upper :B} {:index 3 :lower :c :upper :C}  ]  ?

向量可以是[1 2 3 4:a:b:c:d:A:B:C:D]

或者如果没有简单的方法,有没有一种转换方法

[{:index 1} {:index 2} {:index 3}]  [{:lower :a} {:lower :b} {:lower :c}]   [{:upper :A} {:upper :B} {:upper :C}] 

[{:index 1 :lower :a :upper :A} {:index 2 :lower :b :upper :B} {:index 3 :lower :c :upper :C}]

谢谢!

4 个答案:

答案 0 :(得分:1)

因此,总的来说,当遇到这样的问题时,我会去上游并修复输入格式。一个由任意部分串联而成的向量没有任何意义。为了给出答案,让我们假设这是不可能的。

首先,我们定义一个辅助函数来创建结果图:

(defn make-result [i l u]
    {:index i :lower l :upper u})

然后,我们只需要将此函数映射到三个子序列上即可:

(defn input->output [i]
    (apply map make-result (partition (/ (count i) 3) i)))

我们需要使用apply来生成要用作map参数的子序列序列(请记住,函数arity应该与您传递给map的序列数相匹配-我们的助手很方便地做到这一点)。 / p>

这将适用于上面给出的两个向量。

(input->output [1 2 3 :a :b :c :A :B :C])
({:index 1, :lower :a, :upper :A} {:index 2, :lower :b, :upper :B} {:index 3, :lower :c, :upper :C})
(input->output [1 2 3 4 :a :b :c :d :A :B :C :D])
({:index 1, :lower :a, :upper :A} {:index 2, :lower :b, :upper :B} {:index 3, :lower :c, :upper :C} {:index 4, :lower :d, :upper :D})

如果向量采用其他格式,则可能会令您感到惊讶或失望-也许是为了进行一些输入验证。

答案 1 :(得分:1)

(let [ks [:index :lower :upper]
      xs [1 2 3 :a :b :c :A :B :C]]
  (->> xs
       (partition (/ (count xs) (count ks)))
       (apply map vector)
       (mapv zipmap (repeat ks))))

工作原理:

我们首先通过partition count引导向量:

(partition (/ (count xs) (count ks)) xs)=> ((1 2 3) (:a :b :c) (:A :B :C))

然后转置矩阵:

(apply map vector *1)=> ([1 :a :A] [2 :b :B] [3 :c :C])

最后zipmap,并为每行提供键:

(mapv zipmap (repeat ks) *1)=> [{:index 1, :lower :a, :upper :A} {:index 2, :lower :b, :upper :B} {:index 3, :lower :c, :upper :C}]

答案 2 :(得分:0)

如果您可以提供键值列表,如下所示(为提高可读性而设置的格式):

(def items [[{:index 1}  {:index 2}  {:index 3}]
            [{:lower :a} {:lower :b} {:lower :c}]
            [{:upper :A} {:upper :B} {:upper :C}]])

然后您可以使用以下内容:

(apply map merge items)
;; returns ({:index 1, :lower :a, :upper :A} {:index 2, :lower :b, :upper :B} {:index 3, :lower :c, :upper :C})

这可以通过使用map函数来merge 3个集合中的各个哈希图来实现。首先,将每个集合的第一个元素合并在一起,生成元素{:index 1, :lower :a, :upper :A},然后将每个集合的第二个元素合并,依此类推。

由于map merge的参数是一个集合,因此您需要使用apply来提供map的参数。

答案 3 :(得分:0)

我不是Clojure专家,但这也许会有所帮助:

; your data
(def x [1 2 3 :a :b :c :A :B :C])

; resolve symbols and numbers to strings
(def xa (map (fn [e] (if (keyword? e) (name e) (str e))) x))


; split into three sequences and zip this lists together
(let [xan (filter (fn [e] (not (empty? (re-matches #"[0-9]" e)))) xa)
     xaa (filter (fn [e] (not (empty? (re-matches #"[a-z]" e)))) xa)
     xaA (filter (fn [e] (not (empty? (re-matches #"[A-Z]" e)))) xa)]
     (map-indexed (fn [i e] {:index e :lower (nth xaa i) :upper (nth xaA i)}) xan )) 

您只需构建三个序列并对其进行迭代,然后使用索引访问另一个序列中的相应元素。