Tomas PetricekとJon Skeetの著書「Real-World Functional Programming」(2人のSO Gurus、btw、両者のおかげで) 次の関数は、277ページで、のような特別なもの、アカウント側の値を考慮して、アレイ上の三点の平均を計算する方法を紹介します:F#の機能的結合反復:パフォーマンスの問題と好ましい機能スタイル
let blurArray (arr:float[]) =
let res = Array.create arr.Length 0.0
res.[0] <- (arr.[0] + arr.[1])/2.0
res.[arr.Length-1] <- (arr.[arr.Length - 2] + arr.[arr.Length -1 ])/2.0
for i in 1 .. arr.Length - 2 do
res.[i] <- (arr.[i-1] + arr.[i] + arr.[i+1])/3.0
res
私は機能があっても、外部の世界のために不変であることを理解内部的に突然変異と割り当てを採用する。また、それは本当に不可欠ですが、宣言的なスタイルを維持して構成し、採用することができます。それにもかかわらず、私は高次関数などにもっと慣れ親しむための運動として、機能的な解決策を考え出しました。私は解決策を報告し、私の質問を表明します。最初に私は
let computeElementsAverage (myArray:float[]) myIndex (myElement:float) =
match myIndex with
| 0 -> (myArray.[0..1] |> Array.average)
| lastInd when lastInd = (myArray.Length -1) -> (myArray.[lastInd-1..lastInd] |> Array.average)
| anIndex -> (myArray.[anIndex -1 .. anIndex + 1 ] |> Array.average)
は、ヘルパー関数定義(私はindecesの(リストを抽象化している可能性が - >フロート)のマッチ句のパターンですが、私はそれやり過ぎと考えられます)。
その後blurArrayの同等は次のようになります。
let blurArray' (arr:float[]) =
let mappingFcn = arr |> computeElementsAverage
arr |> (Array.mapi mappingFcn)
は、最後に私の質問:手続の最も推奨される機能的な方法であるもの
真っ先?私は特に、Array.mapiの要件のために、computeElementsAverageの要素型(float)の最後の要素を宣言しなければならないという事実は嫌いです。使用しない議論を避けて、より良い方法がありますか?
第2に:performancewise私のコードは、はるかに遅く、期待されていた。元のコードより1/10速く動作します。そのようなパフォーマンスに大きな打撃を与えることなく高次機能に依然として依存する他のソリューション?
最後に、いくつかの複数のインデクスに依存するデータ構造(配列など)全体で計算を実行する一般的な方法は何ですか?あなたが見ることができるように、私が思いついた方法は、mapiスキャン機能を使用しており、構造自体を含むクロージャを使用しています。あなたの好みの方法は何ですか?
PS:(blurArrayのオリジナルバージョンは、入力として、私はちょうど私のバージョンでList.averageを使用するフロートに[]を変更した[] int型を使用しています)
パフォーマンスの比較は純粋ではありません。 'float'と' int'はペナルティを導入します。 –
@Fyodor、なぜ私は元のコードでもfloatを使用しています。 blurArrayの元のバージョンはint [] - > int []で、私はそれをfloat [] - > float []に微調整しました。おかげで –