【问题标题】:Best way of accumulating values in a map depending on conditional result根据条件结果在地图中累积值的最佳方法
【发布时间】:2015-10-12 16:32:38
【问题描述】:

我在 Java 中有一个算法,它评估输入变量,如果它们不为空,它会进行一些处理并将其关联到映射中。例如:

myMap = new HashMap()

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

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

考虑到 Clojure 通常没有状态,我如何使用它以惯用的方式表达上面的算法?

还有一个信息是,如果变量为空,则不应评估进程函数,因为它会产生空指针异常。所以像 assoc-not-nil 这样的东西不会做:(

谢谢。

【问题讨论】:

    标签: dictionary clojure


    【解决方案1】:

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

    user> (let [a 4 b nil]
            (cond-> {}
              a (assoc a (* a a 42))
              b (assoc b (* b b 47 b))))
    {4 672}
    

    这从一个空映射 {} 的初始状态开始,然后如果 a 为真,它使用 a 之后的表达式结果作为下一阶段的值,如果它不是真值,则将值不变地传递给下一阶段。

    如果我是从一个集合中构建结果,那么我会使用如下函数来减少它:

    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}
    

    或者也许采取更简单的方法,首先过滤掉不应该对答案有贡献的数据,然后放心地减少它。

    【讨论】:

    • reduce 的 IMO 版本更好的是 (into {} (for [new-thing data :when new-thing] [new-thing (* new-thing 42)]))
    • 是的,这样更优雅。我喜欢阅读时进入 ... for ... 的方式。
    • 我几乎不需要使用reduce 来构建地图:into/for 非常灵活,你几乎可以用它来做任何事情,尽管它显然不如@987654330 强大@.
    【解决方案2】:

    如果没有关于 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])
    

    只有当你命名 vars (a,b,c,d) 飞来飞去而不是已经在某种 seq 上运行时,这个解决方案才真正有意义。 还有可能更好的方法

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-22
      • 1970-01-01
      相关资源
      最近更新 更多