用循环递归计算胜率
Calculate winrate with loop recur
(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
在最后一行 returns [0 0 50 0 25]
。我正在努力 return [0 50 33.33333333333333 50 60]
.
我对 wins
的增量是否错误?当我为每次迭代打印 wins
的值时,我得到
0
nil
1
nil
1
所以我猜我不知何故重置或零 wins
不知何故?
此外,是否可以将整个循环替换为 map/map-indexed 或其他内容?感觉 map 使用起来很完美,但我需要在每次迭代时牢记上一次迭代 wins/total。
谢谢!
这里有一个 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 []}
Wins 将包含到目前为止的胜利,matches 是我们分析的比赛数量,percentage 是到目前为止的百分比。
(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}])
这是一个懒惰的解决方案,使用 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)
您可以按如下方式计算 运行 胜率:
(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,
- 将其转换为浮点数。
(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
在最后一行 returns [0 0 50 0 25]
。我正在努力 return [0 50 33.33333333333333 50 60]
.
我对 wins
的增量是否错误?当我为每次迭代打印 wins
的值时,我得到
0
nil
1
nil
1
所以我猜我不知何故重置或零 wins
不知何故?
此外,是否可以将整个循环替换为 map/map-indexed 或其他内容?感觉 map 使用起来很完美,但我需要在每次迭代时牢记上一次迭代 wins/total。
谢谢!
这里有一个 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 []}
Wins 将包含到目前为止的胜利,matches 是我们分析的比赛数量,percentage 是到目前为止的百分比。
(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}])
这是一个懒惰的解决方案,使用 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)
您可以按如下方式计算 运行 胜率:
(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,
- 将其转换为浮点数。