2011-01-13 22 views
7

私は別のシーケンスのn番目の要素からなるシーケンスを作成する方法を探していますが、エレガントな方法でこれを行う方法は見当たりません。私はもちろん、何かをハックすることができますが、私は見ていないライブラリ関数があるのだろうかと思います。シーケンスのn番目の要素を取得する

名前が-iで終わるシーケンス関数は、要素がn番目の(nの倍数)番目の要素を認識するためにはかなり良いようですが、iterimapiしか表示されませんそのうちの1つは実際にタスクに役立ちます。

例:

let someseq = [1;2;3;4;5;6] 
let partial = Seq.magicfunction 3 someseq 

その後partial[3;6]でなければなりません。そこにそれのようなものはありますか?

編集:私はそれほど野心的ではないですし、nが知られている/一定にするために許可した場合

が、その後、私はちょうど、以下が動作する必要があることがわかりました:

let rec thirds lst = 
    match lst with 
    | _::_::x::t -> x::thirds t // corrected after Tomas' comment 
    | _ -> [] 

うこれを短く書く方法がありますか?

+3

リストの各要素を 'Some'または' None'に変換し、 'None'sを' filter'して、それらを未修飾型に再度マップすることができます。 –

+0

あなたの解を使ったリストはうまく見えます(タプルのリストを使う '(_、_、x):: tの代わりに' _ :: _ :: x :: t'を書いたかったでしょう) 'Seq'はリスト以外のコレクションでも動作しますが、それは問題ではないかもしれません。リストのバージョンは素晴らしい機能コードです –

+0

もちろん、それは' _ :: _ :: x :: t'は、ここに貼り付ける前にコンパイラに依頼しておかなければならないでしょう –

答えて

8

あなたは他の機能とmapiを構成することにより、動作を取得することができます:

let everyNth n seq = 
    seq |> Seq.mapi (fun i el -> el, i)    // Add index to element 
     |> Seq.filter (fun (el, i) -> i % n = n - 1) // Take every nth element 
     |> Seq.map fst        // Drop index from the result 

Annonにより示唆されるようにオプションとchooseを使用したソリューションは、2つだけの機能を使用することになりますが、最初の1の体が少しだろう複雑です(原則は本質的に同じです)。

直接IEnumeratorオブジェクトを使用して、より効率的なバージョンを書くのはあまりにも難しいことではありません。

let everyNth n (input:seq<_>) = 
    seq { use en = input.GetEnumerator() 
     // Call MoveNext at most 'n' times (or return false earlier) 
     let rec nextN n = 
      if n = 0 then true 
      else en.MoveNext() && (nextN (n - 1)) 
     // While we can move n elements forward... 
     while nextN n do 
      // Retrun each nth element 
      yield en.Current } 

はEDIT:スニペットはここにも利用可能である:それはので、このような状況ではうまく動作Seq.choosehttp://fssnip.net/1R

+0

誰がより速いのか、あなたか「Anon」か分かりませんが、どちらも同じ提案ですか、それはひどく効率的ですね。 –

+0

非常に効率的ではありません(カバーの下に3つのイテレータを使用しているため、いくつかの追加の関数呼び出しと迂回があります)が、それほど悪くないかもしれません(割り当てられる必要のある中間リストはありません)。より効率的なバージョンのためには、(シーケンス式で)突然変異が必要な場合や、根底にある 'IEnumerator'を使用する場合 –

9

mapiラムダ内のfilter作業を行うことができます。

let everyNth n elements = 
    elements 
    |> Seq.mapi (fun i e -> if i % n = n - 1 then Some(e) else None) 
    |> Seq.choose id 

hereと同様です。

+0

ニースとエレガント! –

+0

ええ、私もそれが好きです! :) –

関連する問題