用循环递归计算赢率

时间:2019-01-27 13:52:15

标签: clojure clojurescript

(defn to-percentage [wins total]
  (if (= wins 0) 0
      (* (/ wins total) 100)))

(defn calc-winrate [matches]
  (let [data (r/atom [])]
    (loop [wins 0
           total 0]
      (if (= total (count matches))
        @data
        (recur (if (= (get (nth matches total) :result) 1)
                 (inc wins))
               (do
                 (swap! data conj (to-percentage wins total))
                 (inc total)))))))

(calc-winrate [{:result 0} {:result 1} {:result 0} {:result 1} {:result 1}])

我得到以下代码,最后一行calc-winrate返回[0 0 50 0 25]。我正在尝试使其返回[0 50 33.33333333333333 50 60]

我为wins进行的增量错误吗?当我为每次迭代打印wins的值时,都会得到

0
nil
1
nil
1

所以我猜我以某种方式重置或为wins为零?

也可以用map / map-indexed代替整个循环吗?感觉地图会是完美的选择,但每次迭代我都需要牢记先前的迭代获胜/总数。

谢谢!

4 个答案:

答案 0 :(得分:1)

这是一个懒惰的解决方案,使用reductions来获取一系列连续的获胜总数,换能器1)将轮数与连续的总数相加2)除以对3)将分数转换为百分比:

(defn calc-win-rate [results]
  (->> results
       (map :result)
       (reductions +)
       (sequence
         (comp
           (map-indexed (fn [round win-total] [win-total (inc round)]))
           (map (partial apply /))
           (map #(* 100 %))
           (map float)))))

(calc-win-rate [{:result 0} {:result 1} {:result 0} {:result 1} {:result 1}])
=> (0.0 50.0 33.333332 50.0 60.0)

答案 1 :(得分:1)

您可以如下计算奔跑赢率:

(defn calc-winrate [matches]
  (map
    (comp float #(* 100 %) /)
    (reductions + (map :result matches))
    (rest (range))))

例如

=> (calc-winrate [{:result 0} {:result 1} {:result 0} {:result 1} {:result 1}])
(0.0 50.0 33.333332 50.0 60.0)

map按两个序列进行操作:

  • (reductions + (map :result matches))-获胜的总和;
  • (rest (range))))-(1 2 3 ... ),对应的匹配数。

map ping函数(comp float #(* 100 %) /)

  • 划分序列的相应元素,
  • 将其乘以100,然后
  • 将其转换为浮点数。

答案 2 :(得分:0)

这是带有reduce的解决方案:

(defn calc-winrate [matches]
  (let [total-matches (count matches)]
    (->> matches
         (map :result)
         (reduce (fn [{:keys [wins matches percentage] :as result} match]
                  (let [wins (+ wins match)
                        matches (inc matches)]
                    {:wins wins
                     :matches matches
                     :percentage (conj percentage (to-percentage wins matches))}))
                 {:wins 0 
                  :matches 0
                  :percentage []}))))

因此,这里要做的是保持(和更新)到目前为止的计算状态。 我们在

的地图中执行此操作
 {:wins 0
  :matches 0
  :percentage []}

胜利将包含到目前为止的胜利,比赛是我们分析过的比赛次数,而百分比是到目前为止的百分比。

答案 3 :(得分:0)

 (if (= (get (nth matches total) :result) 1)
             (inc wins))

您的if如下:

 (if (= (get (nth matches total) :result) 1)
             (inc wins)
             wins  ; missing here , other wise it will return a nil, binding to wins in the loop
)

如果要减价,

(defn calc-winrate2 [ x y ]
  (let [ {total :total r :wins  } x
        {re :result } y]
    (if (pos? re )
      {:total (inc total) :wins (inc r)}
      {:total (inc total) :wins r}
      )
    )
  )

(reductions calc-winrate2 {:total 0 :wins 0} [   {:result 0} {:result 1} {:result 0} {:result 1} {:result 1}])