2016-12-15 6 views
2

コンジットを使用してストリーム形式のデータを解析しています。ストリームのある時点で私は12番目の要素ごとに必要とします。これを行う便利な方法はありますか?コンジットストリームのすべてのn番目の要素を保持する

私は現在、明示的にちょうど最初の要素を返すために12個の要素を待っている:それは作業を行い

get12th :: Monad m => Conduit Int m Int 
get12th = loop 
    where 
    loop = do 
     v1 <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     case v1 of 
      Nothing -> return() 
      Just x -> do 
       yield x >> loop 

が、これはそれを行うための最善の方法である場合、私は思ったんだけど。

+0

また、現在のものを配信する前に束の要素を待つことになります( 'v1 < - await'は一番下が良いでしょう - あなたのトランポリンコールは' await'で始めるべき事柄を扱うことができます) – Alec

+0

@アレック私はあなたが言っていることを理解しており、私は念頭に置いて解決策を持っています。しかし、「v1 < - await」を底に動かすことが問題を解決する方法はわかりません。 –

+0

ここでは、次の要素を送信する前に余分な11要素を待ちます(11要素前に受信しました!)。 'v1 < - await'を動かすと、すぐに' v1'を送ります。 – Alec

答えて

2

アレック、チャド・ギルバートとマイケルSnoymanのおかげで、私は次の解決策に来ている:このソリューションは、重複待ち受けを取り除くためにdrop機能を使用しています

get12th :: Monad m => Conduit Int m Int 
get12th = loop 
    where loop = do 
      v <- await 
      case v of 
      Just x -> yield x >> CL.drop 11 >> loop 
      Nothing -> return() 

。他の値を待つ前に、それを受け取るとすぐに最初の値を返します。

7

replicateM_を使用すると、重複しているawait行を取り除くことができます。

v1 <- await 
replicateM_ 11 await 
case v1 of 
    ... 
+3

['drop'関数](https://www.stackage.org/haddock/lts-7.13/conduit-1.2.8/Data-Conduit-List.html#v:drop)はおそらく関連性があります。 –

+0

@MichaelSnoyman良い点! Dropはメモリ内の値を保持する必要がないため、おそらくより効率的です。私は 'replicateM_11が待っているかどうかはわかりませんが。 –

+1

@MichaelSnoymanあなたは正しいようです。 'drop'関数は最も効率的であるようです。重複した 'await'sを' replicateM_11 await'に置き換えると、パフォーマンスに(少しでも)悪影響があるようです。 'replicateM_11'を' Data.Conduit.List.drop 11 'に置き換えると、パフォーマンスが著しく向上するようです。 –

関連する問題