我正在将现有的python
代码转换为F#
,行数增加了很多,不确定我是否做错了,或者有一个想要优化的代码:
我想要处理这个Array
:
let series = [|30;21;29;31;40;48;53;47;37;39;31;29;17;9;20;24;27;35;41;38;
27;31;27;26;21;13;21;18;33;35;40;36;22;24;21;20;17;14;17;19;
26;29;40;31;20;24;18;26;17;9;17;21;28;32;46;33;23;28;22;27;
18;8;17;21;31;34;44;38;31;30;26;32|]
<{1>}中的是:
Python
第1部分
在series = [30,21,29,31,...,26,32]
我就是这样:
Python
转换为def initial_seasonal_components(series, slen):
seasonals = {}
season_averages = []
n_seasons = int(len(series)/slen)
# compute season averages
for j in range(n_seasons):
season_averages.append(sum(series[slen*j:slen*j+slen])/float(slen))
时我最终得到了这个:
F#
第2部分
在open System.Collections.Generic
let initial_seasonal_components (series : int []) (slen : int) : Dictionary<int, double> =
let seasonals = new Dictionary<int, double>()
let mutable seasonAverages = []
let nSeasons = series.Length / slen
// compute season averages
for i in 0 .. nSeasons-1 do
seasonAverages <-
series
|> Array.sub <|| (slen * i, slen)
|> Array.sum
|> float
|> fun s -> s / (slen |> float)
|> fun e -> [e]
|> List.append seasonAverages
我就是这样:
Python
转换为for i in range(slen):
sum_of_vals_over_avg = 0.0
for j in range(n_seasons):
sum_of_vals_over_avg += series[slen*j+i]-season_averages[j]
seasonals[i] = sum_of_vals_over_avg/n_seasons
时我最终得到了这个:
F#
我在这里做错了什么,或者这是我能得到的优化代码!!
更新
来自here的完整'Python`代码:
for i in 0 .. slen-1 do
let mutable sumOfValsOverAvg = 0.0
for j in 0 .. nSeasons-1 do
sumOfValsOverAvg <-
series
|> Array.item (slen*j+i)
|> float
|> fun el -> el + sumOfValsOverAvg - seasonAverages.[j]
seasonals.Add (i, sumOfValsOverAvg / (nSeasons |> float))
这里是我的等效series = [30,21,29,31,40,48,53,47,37,39,31,29,17,9,20,24,27,35,41,38,
27,31,27,26,21,13,21,18,33,35,40,36,22,24,21,20,17,14,17,19,
26,29,40,31,20,24,18,26,17,9,17,21,28,32,46,33,23,28,22,27,
18,8,17,21,31,34,44,38,31,30,26,32]
def initial_seasonal_components(series, slen):
seasonals = {}
season_averages = []
n_seasons = int(len(series)/slen)
# compute season averages
for j in range(n_seasons):
season_averages.append(sum(series[slen*j:slen*j+slen])/float(slen))
sarr = [str(a) for a in season_averages]
print(", " . join(sarr))
# compute initial values
for i in range(slen):
sum_of_vals_over_avg = 0.0
for j in range(n_seasons):
sum_of_vals_over_avg += series[slen*j+i]-season_averages[j]
seasonals[i] = sum_of_vals_over_avg/n_seasons
return seasonals
代码:
F#
答案 0 :(得分:6)
你需要以不同的方式思考,在F#中,mutability不是默认的。
对于第1部分,您可以这样做:
open System.Collections.Generic
let initial_seasonal_components (series : int []) (slen : int) =
let seasonals = new Dictionary<int, double>()
series |> Array.map float |> Array.chunkBySize slen |> Array.map Array.average
对于第2部分,您也可以采用不同的方法:
[|0..slen-1|]
|> Array.map (fun i ->
i, Array.zip grouped seasonAverages
|> Array.fold (fun s (els, av) -> els.[i] + s - av) 0.)
|> Array.map (fun (i, x) -> i, x / float nSeasons)
|> dict
组合所有部分,您可以这样写:
let initialAeasonalComponents (series : int []) slen : IDictionary<int, double> =
let nSeasons = float (series.Length / slen)
let grouped = series |> Array.map float |> Array.chunkBySize slen
let seasonAverages = grouped |> Array.map Array.average
Array.init slen (fun i -> i, (Array.zip grouped seasonAverages
|> Array.fold (fun s (els, av) -> els.[i] + s - av) 0.)
/ nSeasons) |> dict
请注意,与Python方法的主要区别在于我们使用更高阶的函数,并且我们不使用可变性,这使您更容易推理代码。
另请注意,现在F#代码甚至比Python的代码短一些;)