12
让 aBunch = 1000
让偏移量 = 0

让 getIt 偏移 =
  MyIEnumerable
  |> Seq.skip aBunch * offset
  |> Seq.take aBunch
  |> Seq.iter ( .. 一些处理 ...)

使用不同的偏移量调用 getIt() 最终会给我一个“无效操作”异常以及“输入序列的元素不足”的附加信息

我试图理解为什么,因为 Seq.Skip 和 Seq.take 都不会根据在线文档FSharp Collections生成异常

版本:(Visual Studio 2010)测试版 1

4

5 回答 5

27

我知道这是一个老问题,但如果有人像我一样在搜索中遇到这个问题:

如果您最多需要n 个项目,则可以使用Seq.truncate。如果可用的项目少于n个,它不会抛出异常。

于 2010-03-05T01:16:54.653 回答
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 }
于 2009-08-08T02:46:51.907 回答
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 *)
于 2014-08-15T14:02:04.850 回答
3

这是使用内置函数的稍短的“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
于 2016-03-01T21:27:17.453 回答
1
module Seq = 
    let trySkip count source  =
        source |> Seq.indexed |> Seq.filter(fst >> (<=) count) |> Seq.map snd
于 2016-04-12T10:23:44.757 回答