let aBunch = 1000 let offset = 0 let getIt offset = MyIEnumerable |> Seq.skip aBunch * offset |> Seq.take aBunch |> Seq.iter ( .. some processing ...)
使用不同的偏移量调用getIt()最终会给我一个“无效操作”异常,其中包含“输入序列元素不足”的附加信息
我试着理解为什么,因为Seq.Skip和Seq.take都没有根据在线文档生成异常FSharp Collections
版本:(Visual Studio 2010)Beta 1
答案 0 :(得分:24)
我知道这是一个老问题,但万一有人在我的搜索方式中遇到过这个问题:
如果您最多需要 n 项,则可以使用Seq.truncate。如果可用的项目少于 n ,则不会抛出异常。
答案 1 :(得分:7)
如果使用大于序列的值调用,Seq.skip和Seq.take都将抛出此异常。您可以在Seq.fs中查看源代码以了解原因:
let skip count (sequence: seq<_>) =
{ use e = sequence.GetEnumerator()
let latest = ref (Unchecked.defaultof<_>)
let ok = ref false
for i in 1 .. count do
if not (e.MoveNext()) then
raise <| System.InvalidOperationException "the input sequence had insufficient elements"
while e.MoveNext() do
yield e.Current }
let take count (sequence : seq<'T>) =
if count < 0 then invalidArg "count" "the number of elements to take may not be negative"
(* Note: don't create or dispose any IEnumerable if n = 0 *)
if count = 0 then empty else
{ use e = sequence.GetEnumerator()
for i in 0 .. count - 1 do
if not (e.MoveNext()) then
raise <| System.InvalidOperationException "the input sequence had insufficient elements"
yield e.Current }
答案 2 :(得分:3)
对于无例外skip
,您可以将自己的版本添加到Seq模块,如下所示:
module Seq =
let skipSafe (num: int) (source: seq<'a>) : seq<'a> =
seq {
use e = source.GetEnumerator()
let idx = ref 0
let loop = ref true
while !idx < num && !loop do
if not(e.MoveNext()) then
loop := false
idx := !idx + 1
while e.MoveNext() do
yield e.Current
}
与Seq.truncate
(这是一个无例外的Seq.take
等价物相结合 - 它可以在不抛出异常的情况下获得尽可能多的项目。)
[1..10]
|> Seq.skipSafe 20
|> Seq.truncate 5
(* returns empty seq *)
答案 3 :(得分:2)
这是使用内置函数的稍微更短的“skipSafe”实现:
module Seq =
let skipSafe num =
Seq.zip (Seq.initInfinite id)
>> Seq.skipWhile (fun (i, _) -> i < num)
>> Seq.map snd
或者如果您希望直接将其内嵌到当前管道中,请替换
|> Seq.skip num
与
|> Seq.zip (Seq.initInfinite id)
|> Seq.skipWhile (fun (i, _) -> i < num)
|> Seq.map snd
答案 4 :(得分:1)
module Seq =
let trySkip count source =
source |> Seq.indexed |> Seq.filter(fst >> (<=) count) |> Seq.map snd