Clojure:对一组地图中的值求和,直到达到一个值。

时间:2016-02-01 07:16:39

标签: collections clojure maps

我的目标是在地图集合中添加值,直到其中一个地图值达到值。我尝试使用this example 来计算它,但它没有触及我如何才能抓住部分列表。然后返回没有经过的值的集合。像这样的东西

(def foo '({:key 1, :value 2} {:key 1, :value 2} {:key 1, :value 2})
(defn addValuesUp [foo]
  (take-while (< ((apply merge-with + foo) :value) 4) foo))
 and have it return something like this
'({:key 1, :value 2} {:key 1, :value 2})   

相反,我得到一个错误布尔值无法强制转换为clojure.lang.IFn

2 个答案:

答案 0 :(得分:0)

查看take-while的文档:

clojure.core/take-while
([pred coll])
  Returns a lazy sequence of successive items from coll while
  (pred item) returns true. pred must be free of side-effects.
在这种情况下,

pred是一个返回布尔值的函数。在您的代码中,take-while的第一个参数不是函数,而是表达式。

这就是您收到错误ClassCastException java.lang.Boolean cannot be cast to clojure.lang.IFn的原因。这个错误告诉你Clojure在哪里需要一个函数(IFn),但它找到了一个布尔值(表达式的结果)。

一旦你把它变成一个功能,你应该取得进步。但是,在函数实现中可能还需要做更多的工作。

答案 1 :(得分:0)

我将解决问题的方法是在地图中添加一个新密钥,其中包含所有先前值的累积,以便您可以进行简单的接收:

(defn sums-of-values [c]
  (reductions + c))

(defn with-accum [c]
  (map #(assoc %1 :accum %2)
       c
       (sums-of-values (map :value c))))

既然地图有一个:accum插槽,你可以使用take-while:

(take-while (comp (partial >= 4)
                  :accum)
            (with-accum foo))