2009-08-08 3 views
8
 
let aBunch = 1000 
let offset = 0 

let getIt offset = 
    MyIEnumerable 
    |> Seq.skip aBunch * offset 
    |> Seq.take aBunch 
    |> Seq.iter (.. some processing ...) 

Aufruf getIT() mit unterschiedlichen Offsets gibt mir schließlich eine ‚Ungültige Operation‘ Ausnahme mit zusätzlichen Informationen, dassAufruf Seq.skip und Seq.take in F #

‚die Eingangssequenz nicht genügend Elemente hatte‘

Ich versuche, zu verstehen, warum sowohl als die Seq.Skip und Seq.take keine Ausnahme nach der Online-Dokumentation FSharp Collections

Version erzeugen: (Visual Studio 2010) Beta 1

+2

Die Dokumentation sagt nichts über Ausnahmen aus; Die Dokumente sind unvollständig. Ich werde einen doc-Fehler einreichen. – Brian

Antwort

6

beide Seq.skip und Seq.take wird diese Ausnahme beim Aufruf auslösen ed mit einem Wert größer als die Sequenz. Sie können den Quellcode in Seq.fs überprüfen, um zu sehen, warum:

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 } 
20

Ich weiß, dass dies eine alte Frage, aber für den Fall, über das eine kommt jemand in den Weg suche ich tat:

Sie können Verwenden Sie Seq.truncate, wenn Sie höchstens n Artikel möchten. Es wird keine Ausnahme ausgelöst, wenn weniger als n Elemente verfügbar sind.

1

Für eine ausnahmslose skip Sie Ihre eigene Version der Seq-Modul wie folgt hinzufügen:

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 
     } 

In Kombination mit Seq.truncate (das ist eine ausnahmslose Seq.take Äquivalent - es so viel Gegenstände nehmen sind ohne verfügbar ein Wurf Ausnahme).

[1..10] 
|> Seq.skipSafe 20 
|> Seq.truncate 5 

(* returns empty seq *) 
1

Hier ist eine etwas kürzere "skipSafe" Implementierung in Funktionen eingebaut werden:

module Seq = 
    let skipSafe num = 
     Seq.zip (Seq.initInfinite id) 
     >> Seq.skipWhile (fun (i, _) -> i < num) 
     >> Seq.map snd 

Oder wenn Sie möchten Inline einfach in Ihre aktuelle Pipeline direkt ersetzen

|> Seq.skip num 

mit

|> Seq.zip (Seq.initInfinite id) 
|> Seq.skipWhile (fun (i, _) -> i < num) 
|> Seq.map snd 
0
module Seq = 
    let trySkip count source = 
     source |> Seq.indexed |> Seq.filter(fst >> (<=) count) |> Seq.map snd