Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何附加到clojure vec,直到与累计vec相关的特定条件为真?_Clojure - Fatal编程技术网

如何附加到clojure vec,直到与累计vec相关的特定条件为真?

如何附加到clojure vec,直到与累计vec相关的特定条件为真?,clojure,Clojure,对于我的最小示例,我希望将映射附加到vec中,直到其中一个映射字段的总和达到某个限制 这是我的尝试。显然是错误的,因为项在while循环中不会更改 (let [items []] (into items (while (< (reduce + (map :count items)) 100) {:something "x" :count (+ 1 (rand-int 25))}))) (让[项目[]] (进入项目(

对于我的最小示例,我希望将映射附加到vec中,直到其中一个映射字段的总和达到某个限制

这是我的尝试。显然是错误的,因为
项在while循环中不会更改

(let [items []]
    (into items (while (< (reduce + (map :count items)) 100)
              {:something "x"
               :count     (+ 1 (rand-int 25))})))
(让[项目[]]
(进入项目(同时(<(减少+(映射:计数项目))100)
{:某个“x”字
:计数(+1(rand int 25))})

您可以使用
减少
来实现这一点,同时保持
:计数的运行总和:

(defn random-map []
  {:something "x"
   :count     (inc (rand-int 25))})

(reduce
  (fn [[out sum] {:keys [count] :as m}]
    (let [new-sum (+ sum count)]
      (if (< new-sum 100)
        [(conj out m) (+ sum count)]
        (reduced out))))
  [[] 0] ;; initial accumulator: empty output and sum is 0
  (repeatedly random-map))
=>
[{:something "x", :count 7}
 {:something "x", :count 4}
 {:something "x", :count 14}
 {:something "x", :count 10}
 {:something "x", :count 22}
 {:something "x", :count 4}
 {:something "x", :count 20}
 {:something "x", :count 17}]
(apply + (map :count *1))
=> 98
另一种可能更容易理解/使用的措辞:

(as-> (repeatedly random-map) maps
      (map #(assoc %1 :running-sum %2) maps (reductions + (map :count maps)))
      (take-while #(< (:running-sum %) 100) maps))
(as->(重复随机映射)映射
(映射#(关联%1:运行总和%2)映射(减少+(映射:计数映射)))
(取而代之#(<(:运行总和%)100)地图)

reductions
版本更简洁,但需要更多的多元性
map
知识,在某些情况下可能效率较低。

对于一个运行总数,
reductions
是一个很好的答案

如果你有一个更一般的谓词要考虑,请看:

(s/defn取结果
“从基于带集合参数的谓词的集合中获取。
继续从源集合获取数据,直到`(pred)`为false。
如果pred从不为假,则返回'coll'
[pred:-s/Any;采用列表参数的谓词函数
coll:-tsk/列表]
(何时(空?coll)
(throw(ex info)项不能为空“{:coll coll}”)
(让[所有VAL(vec coll)
数值VAL(计算所有VAL)]
(循环[i]1
结果[];从获取第一个值开始
(如果(
以及单元测试:

(dotest
  (let [items     [{:name :a :count 1}
                   {:name :b :count 2}
                   {:name :c :count 3}
                   {:name :d :count 4}
                   {:name :e :count 5}]
        sum-count (fn sum-count-fn [items] (reduce + (map :count items)))]
    (throws? (t/take-while-result #(<= (sum-count %) 0) []))

    (is= (t/take-while-result #(<= (sum-count %) -1) items) [])
    (is= (t/take-while-result #(<= (sum-count %) 0) items) [])
    (is= (t/take-while-result #(<= (sum-count %) 1) items)
      [{:name :a, :count 1}])
    (is= (t/take-while-result #(<= (sum-count %) 2) items)
      [{:name :a, :count 1}])
    (is= (t/take-while-result #(<= (sum-count %) 3) items)
      [{:name :a, :count 1} {:name :b, :count 2}])
    (is= (t/take-while-result #(<= (sum-count %) 4) items)
      [{:name :a, :count 1} {:name :b, :count 2}])
    (is= (t/take-while-result #(<= (sum-count %) 5) items)
      [{:name :a, :count 1} {:name :b, :count 2}])
    (is= (t/take-while-result #(<= (sum-count %) 6) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3}])
    (is= (t/take-while-result #(<= (sum-count %) 7) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3}])
    (is= (t/take-while-result #(<= (sum-count %) 8) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3}])
    (is= (t/take-while-result #(<= (sum-count %) 9) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3}])
    (is= (t/take-while-result #(<= (sum-count %) 10) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3} {:name :d, :count 4}])
    (is= (t/take-while-result #(<= (sum-count %) 11) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3} {:name :d, :count 4}])
    (is= (t/take-while-result #(<= (sum-count %) 14) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3} {:name :d, :count 4}])
    (is= (t/take-while-result #(<= (sum-count %) 15) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3} {:name :d, :count 4} {:name :e, :count 5}])
    (is= (t/take-while-result #(<= (sum-count %) 16) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3} {:name :d, :count 4} {:name :e, :count 5}])))
(dotest
(让[项目[{:名称:a:计数1}
{:name:b:count 2}
{:name:c:count 3}
{:name:d:count 4}
{:name:e:count 5}]
总和计数(fn总和计数fn[项目](减少+(映射:计数项目)))]
(抛出?(t/在结果时进行)#(
(s/defn take-while-result
  "Takes from a collection based on a predicate with a collection argument.
  Continues taking from the source collection until `(pred <taken-items>)` is falsey.
  If pred is never falsey, `coll` is returned."
  [pred :- s/Any ; a predicate function  taking a list arg
   coll :- tsk/List]
  (when (empty? coll)
    (throw (ex-info "items must not be empty" {:coll coll})))
  (let [all-vals (vec coll)
        num-vals (count all-vals)]
    (loop [i      1
           result []] ; start by taking first value
      (if (< num-vals i)
        result
        (let [test-vals (subvec all-vals 0 i)]
          (if (not (pred test-vals))
            result
            (recur (inc i) test-vals)))))))
(dotest
  (let [items     [{:name :a :count 1}
                   {:name :b :count 2}
                   {:name :c :count 3}
                   {:name :d :count 4}
                   {:name :e :count 5}]
        sum-count (fn sum-count-fn [items] (reduce + (map :count items)))]
    (throws? (t/take-while-result #(<= (sum-count %) 0) []))

    (is= (t/take-while-result #(<= (sum-count %) -1) items) [])
    (is= (t/take-while-result #(<= (sum-count %) 0) items) [])
    (is= (t/take-while-result #(<= (sum-count %) 1) items)
      [{:name :a, :count 1}])
    (is= (t/take-while-result #(<= (sum-count %) 2) items)
      [{:name :a, :count 1}])
    (is= (t/take-while-result #(<= (sum-count %) 3) items)
      [{:name :a, :count 1} {:name :b, :count 2}])
    (is= (t/take-while-result #(<= (sum-count %) 4) items)
      [{:name :a, :count 1} {:name :b, :count 2}])
    (is= (t/take-while-result #(<= (sum-count %) 5) items)
      [{:name :a, :count 1} {:name :b, :count 2}])
    (is= (t/take-while-result #(<= (sum-count %) 6) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3}])
    (is= (t/take-while-result #(<= (sum-count %) 7) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3}])
    (is= (t/take-while-result #(<= (sum-count %) 8) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3}])
    (is= (t/take-while-result #(<= (sum-count %) 9) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3}])
    (is= (t/take-while-result #(<= (sum-count %) 10) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3} {:name :d, :count 4}])
    (is= (t/take-while-result #(<= (sum-count %) 11) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3} {:name :d, :count 4}])
    (is= (t/take-while-result #(<= (sum-count %) 14) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3} {:name :d, :count 4}])
    (is= (t/take-while-result #(<= (sum-count %) 15) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3} {:name :d, :count 4} {:name :e, :count 5}])
    (is= (t/take-while-result #(<= (sum-count %) 16) items)
      [{:name :a, :count 1} {:name :b, :count 2} {:name :c, :count 3} {:name :d, :count 4} {:name :e, :count 5}])))