2009-08-08 6 views
8
 
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 कॉलिंग

मैं कोशिश समझने के लिए क्यों, दोनों Seq.Skip और Seq.take ऑनलाइन प्रलेखन के अनुसार एक अपवाद उत्पन्न नहीं करते हैं FSharp Collections

संस्करण: (दृश्य स्टूडियो 2010) बीटा 1

+2

प्रलेखन अपवादों के बारे में कुछ भी नहीं कहता है; दस्तावेज़ अपूर्ण हैं। मैं एक दस्तावेज़ बग फाइल करूंगा। – Brian

उत्तर

6

दोनों 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 } 
20

मैं जानता हूँ कि यह एक पुराने सवाल है, लेकिन इस मामले में किसी को एक में इस भर आता है जिस तरह से मैंने किया खोज:

आप कर सकते हैं यदि आप n आइटम पर सबसे अधिक Seq.truncate का उपयोग करें। यदि n आइटम से कम उपलब्ध हैं तो यह अपवाद नहीं फेंक देगा।

1

एक exceptionless 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 (जो एक exceptionless Seq.take बराबर है - यह रूप में ज्यादा आइटम ले जाएगा एक फेंकने के बिना उपलब्ध हैं अपवाद)।

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

या यदि आपने अभी आपकी वर्तमान पाइपलाइन में इनलाइन करना चाहते हैं, की जगह

|> Seq.skip num 
साथ

:

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

(* returns empty seq *) 
1

यहाँ एक से थोड़ा कम "skipSafe" कार्यान्वयन कार्यों में बनाया उपयोग कर रहा है

|> 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 
संबंधित मुद्दे