我想使用Clojure哈希图来定义广义 vector 。在此图片中,哈希图{:x 3:y 2:z(-3)}表示符号表达式3x + 2y-3z。
我想要一个函数gen +,它充当哈希图的加法运算,并且满足以下约束:
(gen+ {:x 1} {:x 2})
;= {:x 3}
(gen+ {:x 1} {:y 2})
;= {:x 1 :y 2}
(gen+ {:x 1} {})
:= {:x 1}
(gen+ {:x 1 :y 0} {:z 0})
;= {:x 1}
({:x 3} :y) ;= nil
,而不是0。因此,gen +应该以与0相同的方式对待nil值,例如(gen+ {:x 1 :y 0} {:x nil :y nil})
{:x 1}
显而易见的是,为什么这种形式主义将哈希图视为广义 vector 。 Clojure解释类似于[x0 x1 x2]之类的 vector ,与哈希图{:0 x0:1 x1:2 x2}几乎相同,只是略有不同,我不太了解。因此,如果我们将gen +应用于两个 vector ,则它实际上应与应用于它们的+相同。这使我们能够轻松处理稀疏 vector ,以及添加不同大小的 vector 。例如。,
(gen+ [0 0 0 4] [0 0 0 0 0 0 0 0 0 9])
;= {:4 4 :9 9}
这是我对哈希图和 vector 不了解的内容。如果我将hashmap称为函数,则需要应用诸如:2之类的key参数。另一方面,如果我将 vector 称为函数,则需要应用索引参数,例如2。例如,
({:2 2} :2)
;= 2
([0 1 2] 2]
;= 2
即使您无法使用gen +函数,也可以解释一下为什么将hashmap和vector称为函数时行为不同?
最佳答案
这将首先删除nil
和0
值,然后按照M Smith的建议添加带有merge-with
的 map :
(defn filter-vals
[pred m]
(into {} (filter (fn [[k v]] (pred v))
m)))
(defn gen+
[m1 m2]
(letfn [(keep-val? [val]
(and (not (nil? val))
(not (zero? val))))]
(merge-with +
(filter-vals keep-val? m1)
(filter-vals keep-val? m2))))
开始添加之前,您需要过滤掉所有
nil
,否则最终将尝试向数字添加nil
,这是一个错误。但是,我概述的gen+
可能返回带有0
值的条目(请考虑(gen+ {:x 1} {:x -1})
)。如果有可能根据您的输入,并且需要避免这种情况,则需要在合并后添加另一个过滤器:
(defn gen+
[m1 m2]
(letfn [(keep-val? [val]
(and (not (nil? val))
(not (zero? val))))]
(->> (merge-with +
(filter-vals keep-val? m1)
(filter-vals keep-val? m2))
(filter-vals keep-val?))))
最后,这是一个可以处理可变数量的输入映射的版本:
(defn gen+
[& maps]
(letfn [(keep-val? [val]
(and (not (nil? val))
(not (zero? val))))]
(->> (apply merge-with
+
(map #(filter-vals keep-val? %) maps))
(filter-vals keep-val?))))
因此,例如:
(gen+ {:x 1} {:x 3} {:x 4 :y 5}) ;=> {:x 8, :y 5}
关于映射和 vector 之间的区别,请这样考虑:映射是从键到值的函数,而 vector 是从索引到值的函数。在这两种情况下,如果都有一个“键”(一个 vector 是索引),则可以使用它来查找关联的值。
我同意您到目前为止就重载
clojure.core/+
所获得的答案和评论(我不推荐);也就是说,这是一种解决方法,但有很多警告:(ns overload.example
(:refer-clojure :exclude [+])
(:require [clojure.core :as clj]))
(in-ns 'overload.example)
(defn gen+ ...)
(defn + [& xs]
(if (every? number? xs)
(reduce clj/+ 0 xs)
(apply gen+ xs)))
关于vector - Clojure HashMap 作为广义向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19669917/