2016-05-24 9 views
2

私はいくつかの要素を生成してリストに返す関数を持っています。この関数は、返された要素をフィルタリングするためのパラメータをとります。関数は次のようになります。複数の計算式を含むリストを追加する

let create x = [1..1000] |> List.filter (fun c -> (c % x) = 0) 

この関数を複数の条件で呼び出し、すべての結果を1つのリストに追加したいと思います。

最初に私は、このやって考えていた:

let result = (create 100) 
      |> List.append (create 300) 
      |> List.append (create 500) 
      |> List.append (create 3) 
printf "%A" result 

をしかし、私はこのソリューションは、エレガントでList.append式で繰り返し見つけることができませんでした。

は、私は2番目の解決策を試してみました:

let result = [100; 300; 500; 3] |> List.map (fun c -> create c) 
           |> List.reduce (fun acc c -> acc |> List.append c) 
printf "%A" result 

このソリューションは、より簡潔であるが、私はそれについて好きではない何かがあります。私たちが達成しようとしたことを推測することは、あまり明確ではなく、より困難でした。

だから、私は第三ソリューションを探してと計算式を使用して新しいソリューションを実装することを試みた。

type AppendBuilder() = 
    member this.Bind (x, f) = f x |> List.append x 
    member this.Return x = x 

をし、そのようにそれを使用します。

let append = new AppendBuilder() 
let result = append { 
    let! a = create 100 
    let! b = create 300 
    let! c = create 500 
    let! d = create 3 

    return [] 
} 
printf "%A" result 

この最後のソリューションは、動作し、私はそれを好む。私たちが何をしているのか、繰り返しList.append式がないのかをより理解しやすくなっています。しかし、まだ何かが間違っています。私はreturn []の部分が好きではありませんが、これは不自然で不明瞭です。しかし、このトリックはそれを動作させるために必要です。

第3の解決策は私のお気に入りですが、これが私の問題を解決する正しい方法であるかどうかはわかりません。それは問題を解決する、私は正しい結果を得るが、これが正しいアプローチであるかどうかわからない。

第3の解決策を自分の意図を混乱させることなく維持できますか?解決策はそれをそのまま維持するのに十分明確ですか?私は、コード(ここではList.appendと呼んでいます)を寄生させる反復的な表現なしに、アクション(ここではcreate xと呼んでいます)に焦点を当てたソリューションを探しています。

あなたが seq計算の怠惰の恩恵を受けることができる
+5

のような '[100; 300; 500; 3] |> List.collectは私が投稿の答えのすべてにわたり@JohnPalmerのソリューションを好む –

+0

をcreate' 。これは、ライブラリ関数を最大限に活用しています。 - すべてのポストされたソリューションとは対照的に - 前の計算ステップからの引数( '[100; 300; 500; 3]')を許可します。 –

+0

はい、計算を出発点としてデータの変換として表現し、他の要件(たとえば、パフォーマンス)がそれを要求する場合は、それから離れるようにしてください。 – TheQuickBrownFox

答えて

5
let result = 
    [ 
     yield! [ 100 .. 100 .. 1001] 
     yield! [ 300 .. 300 .. 1001] 
     yield! [ 500 .. 500 .. 1001] 
     yield! [ 3 .. 3 .. 1001] 
    ] 

注:あなたがF#の値1001の代わりに1000の値を使うことができるので、私はそれらをもっとフレンドリーに見つけることができます。

createの機能が常にstep functionの場合、リストの組み込み機能を使用する方が理にかなっています。create関数を使用して、リストの組み込み機能を使用できない場合は、John Palmerのコメントが理にかなっています。

let result = 
    [100;300;500;3] 
    |> List.collect create 

変動がcreate関数の値がパラメータとして来ることができるようになりAnton Schwaighoferによってコメントに示唆しています。

let makeList parms = 
    parms 
    |> List.collect create 

、その後、これは答えとして要求されたので

let result = makeList [100;300;500;3] 

あるいはpointfree

let makeList = List.collect create 
1

seq { 
    yield! create 100 
    yield! create 300 
    yield! create 500 
    yield! create 3 
} |> List.ofSeq 

と3つ、あなたはリストの内包を使用することがありますあなたのお気に入りのバージョンであれば、List.ofSeq

2

を使用してリストを計算:

let result = 
    [ yield! create 100 
     yield! create 300 
     yield! create 500 
     yield! create 3 ] 
7

として使用すること:最も簡単な方法はどのesentially List.collectを使用することです

マップを作成し、リストを1つのステップで結合します。

この場合の解決策は、見えるものについて

[100;300;500;3] |> List.collect create 
+0

@Guy Coderは彼の答えですでにこの方法を指摘していました。 –

関連する問題