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

How to create a mapping based on several vectors?

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

(定义列 ["col1" "col2" "col3" "col4"])

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

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

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

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

怎么做?

我建议您将 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

解决此问题的一种方法是同时映射所有向量。但是,您需要为地图键指定特定名称(例如 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))})

这基本上为生成的地图中的每个 "row" 建立了结果。这里需要注意的是 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