Dictionary 根据条件结果在映射中累积值的最佳方法

Dictionary 根据条件结果在映射中累积值的最佳方法,dictionary,clojure,Dictionary,Clojure,我有一个Java算法,它计算输入变量,如果它们不为null,它会进行一些处理并将其关联到一个映射中。e、 g: myMap = new HashMap() if ( a != null ) myMap.put( "a", process( a ) ) if ( b != null ) myMap.put( "b", process( b ) ) 考虑到Clojure通常没有状态,如何使用它以惯用的方式表达上述算法 另外一个信息是,如果变量为null,则不应计算进程函数,因为它将

我有一个Java算法,它计算输入变量,如果它们不为null,它会进行一些处理并将其关联到一个映射中。e、 g:

myMap = new HashMap()

if ( a != null )
   myMap.put( "a", process( a ) )

if ( b != null )
   myMap.put( "b", process( b ) )
考虑到Clojure通常没有状态,如何使用它以惯用的方式表达上述算法

另外一个信息是,如果变量为null,则不应计算进程函数,因为它将产生null指针异常。所以像assoc not nil这样的东西是不行的:(


谢谢。

当我想有条件地建立这样的结果时,我倾向于使用
cond->
(条件线程优先)宏

这从空映射的初始状态开始,然后如果a为true,它使用a之后的表达式的结果作为下一阶段的值,如果它不是truthy,它会将未更改的值传递给下一阶段

如果我从一个集合中构建结果,那么我会使用如下函数对其进行缩减:

user> (let [data [1 2 3 nil 4 5 nil 6]]
        (reduce (fn [result-so-far new-thing]
                  (if new-thing
                    (assoc result-so-far
                           new-thing
                           (* new-thing 42))
                    result-so-far))
                {}
                data))
{1 42, 2 84, 3 126, 4 168, 5 210, 6 252}

或者可以采取更简单的方法,先过滤掉不应该对答案有帮助的数据,然后减少数据,而不用担心。

如果没有关于a和b的更多信息,可以执行以下操作

其中a、b、c和d的定义如下:

a ;=> 33
b ;=> 44
c ;=> (not set) CompilerException ... Unable to resolve symbol: c in this context ...
d ;=> nil

(->> ['a 'b 'c 'd]
 (filter (comp (complement nil?) resolve)) ; filter unbound symbols ?
 (map #(vector (name %1) (eval %1)))       ; 'a -> ["a" 33] transform
 (filter (comp (complement nil?) second))  ; filter nils
 (map identity))                           ; here identity as dummy-fn for your process-fn
;=> (["a" 33] ["b" 44])
这种解决方案只有在命名变量(a、b、c、d)时才有意义,而不是在某种seq上运行。
还有一种可能更好的方法

reduce的一个版本,在我看来更好的方法是
(插入{}(对于[新事物数据:当新事物][新事物(*new thing 42)])
是的,这更优雅。我喜欢阅读时进入…的方式。我几乎不必使用
reduce
来构建地图:
进入
/
,因为
非常灵活,你几乎可以用它做任何事情,尽管它显然不如
reduce
强大。
a ;=> 33
b ;=> 44
c ;=> (not set) CompilerException ... Unable to resolve symbol: c in this context ...
d ;=> nil

(->> ['a 'b 'c 'd]
 (filter (comp (complement nil?) resolve)) ; filter unbound symbols ?
 (map #(vector (name %1) (eval %1)))       ; 'a -> ["a" 33] transform
 (filter (comp (complement nil?) second))  ; filter nils
 (map identity))                           ; here identity as dummy-fn for your process-fn
;=> (["a" 33] ["b" 44])