我的F#代码比同等的python代码长得多,有什么不对吗?

时间:2018-01-13 09:21:43

标签: f#

我正在将现有的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#

1 个答案:

答案 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的代码短一些;)