如何基于几个向量创建映射?

时间:2015-01-17 13:32:27

标签: clojure

我有一个向量定义表中的列,如下所示

(def column [“col1”“col2”“col3”“col4”])

然后几个向量定义列的类型和约束。

(def maxInclude [nil nil 1000 nil])
(def minInlcude [nil 200 300  nil])
(def columntype [int float int int])

然后我需要得到如下的映射:一个映射条目定义每个列,key是列名,value是该列的类型和约束。

{:col1 {:columntype "int"},
:col2 {:columntype "float" :minInlcude 200},
:col3 {:columntype "float" :minInlcude 300 :maxInclude 1000},
:col4 {:columntype "int" }
}

怎么做?

2 个答案:

答案 0 :(得分:1)

我建议你将columntype定义为符号的向量而不是函数,所以:

(def columntype ['int 'float 'int 'int])

而不是:

(def columntype [int float int int])

另请注意,minInlcude拼写错误,我已将其重命名为minInclude。您可以使用以下命令创建结果(minInclude已重命名,columntype是符号的向量):

(def column ["col1" "col2" "col3" "col4"])
(def maxInclude [nil nil 1000 nil])
(def minInclude [nil 200 300  nil])
(def columntype ['int 'float 'int 'int])

(defn remove-nil-vals [m]
  (into {} (map (fn [e]
                  (vector (key e)
                          (into {} (remove (comp nil? val) (val e)))))
             m)))

(remove-nil-vals
 (reduce merge
         (map #(hash-map (keyword %1) {:columntype (str %2)
                                       :minInclude %3
                                       :maxInclude %4})
              column columntype minInclude maxInclude)))


{:col4 {:columntype "int"},
 :col3 {:columntype "int", :minInclude 300, :maxInclude 1000},
 :col2 {:columntype "float", :minInclude 200},
 :col1 {:columntype "int"}}

符号的Clojure命名约定是连字符而不是CamelCase。因此,您应该考虑使用max-include代替maxInclude

答案 1 :(得分:1)

解决此问题的一种方法是同时映射所有向量。但是,您需要为地图密钥指定特定名称(例如columntype等),因此以下解决方案并非通用:

(defn- constraints [cname type min max]
  {(keyword cname)
   (as-> {:columntype (str type)} cmap
         (if min
           (assoc cmap :minInclude min)
           cmap)
         (if max
           (assoc cmap :maxInclude max)
           cmap))})

这基本上构建了每个"行"的结果。在结果地图中。这里需要注意的是Clojure类型int和float到字符串之间的映射。我想你真的不想对Clojure类型有约束。如果我是对的,您可能应该更改columntype中的数据以使用关键字(即:int, :float)并从上面的str更改为name

然后你可以使用mapv映射所有向量,从每个向量中同时获取第一个值,然后是第二个值,依此类推,并将其提供给constraints函数:

(mapv constraints column maxInclude minInclude columntype) 

这是一个示例运行:

user> (pprint (into {} (mapv constraints column columntype maxInclude minInclude)))
{:col1 {:columntype "clojure.core$int@607af697"},
 :col2 {:maxInclude 200, :columntype "clojure.core$float@4e8b32fb"},
 :col3
 {:maxInclude 300,
  :minInclude 1000,
  :columntype "clojure.core$int@607af697"},
 :col4 {:columntype "clojure.core$int@607af697"}}
nil