地图的 Clojure 向量
Clojure Vector of maps
我是 clojure 编程新手,需要一点帮助。
假设我有一个地图矢量,如图所示。
(def testVMap
[ {:name "AAA" :rate 100 }
{:name "GEICO" :rate 120 }
{:name "PROGRESSIVE" :rate 118} ] )
我该如何做一些操作,比如找到 AAA 的费率,或者看看我是否有 ALLSTAR 的费率,如果费率不存在,我希望能够添加它,我知道我可以添加使用 into 或 conj。
但我主要担心的是发现我的地图有一个特定的名称,如果名称存在,我需要将费率更新为新值。
这是一种方法:
(some #(if (= "GEICO" (:name %)) %) testVMap)
也就是说:Return testVMap
中第一个 :name
等于 "GEICO"
的东西。 #(... % ...)
定义了一个函数,%
作为它的函数参数。这部分(:name %)
returns每个图的值:name
值
如果可能有多个 "GEICO" 地图,而您想要所有地图,请使用 filter
而不是 some
。
这是另一个版本:
(some #(and (= "GEICO" (:name %)) %) testVMap)
您可能还想使用 update
。
编辑:
例如:
(map #(if (= "GEICO" (:name %))
(update % :rate inc)
%)
testVMap)
这里inc
是给一个数加1的函数。您应该将其替换为执行所需转换的函数,例如 #(+ 10 %)
或 (partial + 10)
,它们是同一回事。
#(...)
定义的函数检查:name
的值是否为"GEICO",如果是,则用您提供的函数更新汇率(inc
在这种情况下);否则,#(...)
returns 地图不变。
我会留给你去查找 update
的文档,如果它不能从上下文中自我解释的话。
您也可以使用 mapv
而不是 map
。
毫无疑问,您会希望将所有这些构建到一个或多个函数中。请记住,函数是 Clojure 中的东西——它们是 "data"、第一个 class 对象等。所以在我使用 inc
的地方,你可以有一个函数参数,以及你定义的函数可以接受另一个函数作为它的参数,然后第一个函数将在代码的 update
部分使用它(而不是 inc
)。
关于在您想要的地图不存在时添加地图:如果您不处理一长串地图,我会考虑在不同的步骤中执行此操作。有关可用于测试集合是否包含元素的函数名称,请参阅 Andre 的回答。
但是,请注意,测试向量是否包含不存在的内容需要 Clojure 查看整个向量。使用 Clojure 集而不是向量可能更好,或者考虑使用带有(例如):aaa
、:geico
等作为键的外部映射。在这种情况下,请查看函数 update-in
.
与其直接告诉您如何执行此操作,不如让我向您展示如何找到这种功能。
这两个网站的功能结构很好:
现在您要处理的通常是 集合,如果这不能满足您的要求,您可以寻找特定的 vector 操作。不过第一个应该是collection。然后,您将在两个站点中看到 内容测试 部分。
现在您有以下候选人:
distinct? empty? every? not-every? some not-any?
这里的正确人选是some
:
(some (comp (partial = "AAA") :name) testVMap)
;; => true
查看项目是否存在
(first
(filter
(comp #{"AAA"} :name)
[{:name "AAA" :rate 100}
{:name "GEICO" :rate 120}
{:name "PROGRESSIVE" :rate 118}]))
正在更新您的结构
如果顺序不重要,您可以将结构重组为 name->rate 的映射。例如:
{"AAA" 100 "GEICO" 120}
然后您可以使用update-in
或assoc
更新汇率。
如果订单 很重要,您可以这样做:
(mapv
(fn [{:keys [name] :as v}]
(if (= name "AAA")
(assoc v :rate 500)
v))
[{:name "AAA" :rate 100}
{:name "GEICO" :rate 120}
{:name "PROGRESSIVE" :rate 118}])
添加到您的结构中
您可以使用简单的 conj
添加到它。所以你做一些像
(if (has-item? struct) ;; has-item would be defined using the first section of this answer
(update-item struct ...) ;; update-item using the second section of this answer
(conj struct {:name "AAA" :rate 100}))
当然还有其他选择,但我会首先选择这些。
我是 clojure 编程新手,需要一点帮助。 假设我有一个地图矢量,如图所示。
(def testVMap
[ {:name "AAA" :rate 100 }
{:name "GEICO" :rate 120 }
{:name "PROGRESSIVE" :rate 118} ] )
我该如何做一些操作,比如找到 AAA 的费率,或者看看我是否有 ALLSTAR 的费率,如果费率不存在,我希望能够添加它,我知道我可以添加使用 into 或 conj。 但我主要担心的是发现我的地图有一个特定的名称,如果名称存在,我需要将费率更新为新值。
这是一种方法:
(some #(if (= "GEICO" (:name %)) %) testVMap)
也就是说:Return testVMap
中第一个 :name
等于 "GEICO"
的东西。 #(... % ...)
定义了一个函数,%
作为它的函数参数。这部分(:name %)
returns每个图的值:name
值
如果可能有多个 "GEICO" 地图,而您想要所有地图,请使用 filter
而不是 some
。
这是另一个版本:
(some #(and (= "GEICO" (:name %)) %) testVMap)
您可能还想使用 update
。
编辑: 例如:
(map #(if (= "GEICO" (:name %))
(update % :rate inc)
%)
testVMap)
这里inc
是给一个数加1的函数。您应该将其替换为执行所需转换的函数,例如 #(+ 10 %)
或 (partial + 10)
,它们是同一回事。
#(...)
定义的函数检查:name
的值是否为"GEICO",如果是,则用您提供的函数更新汇率(inc
在这种情况下);否则,#(...)
returns 地图不变。
我会留给你去查找 update
的文档,如果它不能从上下文中自我解释的话。
您也可以使用 mapv
而不是 map
。
毫无疑问,您会希望将所有这些构建到一个或多个函数中。请记住,函数是 Clojure 中的东西——它们是 "data"、第一个 class 对象等。所以在我使用 inc
的地方,你可以有一个函数参数,以及你定义的函数可以接受另一个函数作为它的参数,然后第一个函数将在代码的 update
部分使用它(而不是 inc
)。
关于在您想要的地图不存在时添加地图:如果您不处理一长串地图,我会考虑在不同的步骤中执行此操作。有关可用于测试集合是否包含元素的函数名称,请参阅 Andre 的回答。
但是,请注意,测试向量是否包含不存在的内容需要 Clojure 查看整个向量。使用 Clojure 集而不是向量可能更好,或者考虑使用带有(例如):aaa
、:geico
等作为键的外部映射。在这种情况下,请查看函数 update-in
.
与其直接告诉您如何执行此操作,不如让我向您展示如何找到这种功能。
这两个网站的功能结构很好:
现在您要处理的通常是 集合,如果这不能满足您的要求,您可以寻找特定的 vector 操作。不过第一个应该是collection。然后,您将在两个站点中看到 内容测试 部分。
现在您有以下候选人:
distinct? empty? every? not-every? some not-any?
这里的正确人选是some
:
(some (comp (partial = "AAA") :name) testVMap)
;; => true
查看项目是否存在
(first
(filter
(comp #{"AAA"} :name)
[{:name "AAA" :rate 100}
{:name "GEICO" :rate 120}
{:name "PROGRESSIVE" :rate 118}]))
正在更新您的结构
如果顺序不重要,您可以将结构重组为 name->rate 的映射。例如:
{"AAA" 100 "GEICO" 120}
然后您可以使用update-in
或assoc
更新汇率。
如果订单 很重要,您可以这样做:
(mapv
(fn [{:keys [name] :as v}]
(if (= name "AAA")
(assoc v :rate 500)
v))
[{:name "AAA" :rate 100}
{:name "GEICO" :rate 120}
{:name "PROGRESSIVE" :rate 118}])
添加到您的结构中
您可以使用简单的 conj
添加到它。所以你做一些像
(if (has-item? struct) ;; has-item would be defined using the first section of this answer
(update-item struct ...) ;; update-item using the second section of this answer
(conj struct {:name "AAA" :rate 100}))
当然还有其他选择,但我会首先选择这些。