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
答案 0 :(得分:6)
我认为使用List.length更加“惯用”f#。然后你不需要任何类型的注释。所以:
...
if List.length reversedChunk < chunkSize then
...
答案 1 :(得分:4)
无法推断reversedChunk
的类型,因此您需要指定类型。将第三行更改为:
match state with (reversedResult, reversedChunk : list<'T>) ->
答案 2 :(得分:3)
正如其他人已经提到的那样,您可以使用List.length
代替Length
来完成这项工作。实际上,将当前块长度保持为状态的一部分可能更好,因为List.length
需要遍历整个列表来计算其长度 - 因此每次都会继续迭代块。
以下内容与原始代码几乎相同,但我将folder
转换为普通函数(此处不需要lambda)并删除了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
答案 3 :(得分: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]]
答案 4 :(得分: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]