2

F# は私には簡単ではありません。次のコードは、リストをチャンクすることになっています。何が問題なのかわかりません。助けてください。

let chunk items chunkSize =
    let folder = fun state x ->
        match state with (reversedResult, reversedChunk) ->
            if reversedChunk.Length < chunkSize then
                (reversedResult, x::reversedChunk)
            else
                ((reversedChunk |> List.rev)::reversedResult, [x])
    let alsmostDone = items |> List.fold folder ([], [])
    match alsmostDone with
    | (reversedResult, []) -> reversedResult |> List.rev
    | (reversedResult, lastReversedChunk) -> (lastReversedChunk |> List.rev)::reversedResult |> List.rev

ここに画像の説明を入力

4

5 に答える 5

4

の型はreversedChunk推測できないため、型を指定する必要があります。3 行目を次のように変更します。

match state with (reversedResult, reversedChunk : list<'T>) ->
于 2013-09-17T04:57:36.650 に答える
3

List.length他の人がすでに述べたように、これを機能させる代わりに使用できますLength。実際には、現在のチャンクの長さを状態の一部として保持する方が良い場合があります。これはList.length、リスト全体を反復してその長さを計算する必要があるためです。そのため、毎回チャンクを反復し続けることになります。

以下は元のコードとほとんど同じですがfolder、通常の関数 (ここではラムダは必要ありません) になり、削除しましmatchた (関数宣言で状態を直接パターン マッチできるため)。次に、状態に追加reversedChunkSizeしました:

let chunk items chunkSize =
    let folder (reversedResult, reversedChunk, reversedChunkSize) x =
      if reversedChunkSize < chunkSize then
          (reversedResult, x::reversedChunk, reversedChunkSize + 1)
      else
          ((reversedChunk |> List.rev)::reversedResult, [x], 1)
    let alsmostDone = items |> List.fold folder ([], [], 0)
    match alsmostDone with
    | (reversedResult, [], _) -> 
         reversedResult |> List.rev
    | (reversedResult, lastReversedChunk, _) -> 
         (lastReversedChunk |> List.rev)::reversedResult |> List.rev
于 2013-09-17T14:54:39.190 に答える
1

これは、特定のコーディングの問題というよりも、質問の最初の文に対処するためのものです。

ゼロから独自のアルゴリズムを (再) 発明することに加えて、FP 言語の習得は、標準のコア ライブラリ関数とコンビネータの観点からソリューションの慣用的な考え方を開発することによっても促進されます。解決しようとしていたタスクは、いくつかの単純な慣用的なデータ変換によって達成できます。

let chunk size items =                     // test upon chunk 3 [1..6]
    items                                  // [1;2;3;4;5;6]
    |> List.mapi (fun i x -> (i/size,x))   // [(0, 1); (0, 2); (0, 3); (1, 4); (1, 5); (1, 6)]
    |> Seq.groupBy fst                     // seq [(0, seq [(0, 1); (0, 2); (0, 3)]); (1, seq [(1, 4); (1, 5); (1, 6)])]
    |> Seq.map snd                         // seq [seq [(0, 1); (0, 2); (0, 3)]; seq [(1, 4); (1, 5); (1, 6)]]
    |> Seq.map (Seq.map snd >> Seq.toList) // seq [[1; 2; 3]; [4; 5; 6]]
    |> Seq.toList                          // [[1; 2; 3]; [4; 5; 6]]
于 2013-09-17T06:00:54.893 に答える
1

「GetSlice」バージョン:

let chunk2 size items =
    [
        let arrs = items |> Seq.toArray
        let len = List.length items
        for i in [0..size..len-1] do
            let min = System.Math.Min(i+size, len)
            yield arrs.[i..min-1] |> Array.toList
    ]

let a = chunk2 6 [1..10000]
于 2013-09-17T09:06:59.173 に答える