如何创建基于多个向量的映射?
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
我有一个向量定义 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