2016-08-27 9 views
3

私はHaskellのに新しいです、と私は機能はRubyのslice_whenのような働きたいのHaskellの同等:Rubyのslice_when

slice_when ルビー

a = [1,2,4,9,10,11,12,15,16,19,20,21] 
b = a.slice_when {|i, j| i+1 != j } 
p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]] 

ハスケル

ghci > slice_when (\x y -> x+1 /= y) [1,2,4,9,10,11,12,15,16,19,20,21] 

=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]] 

どうもありがとうございました。

+0

限りプレリュード機能として、[ 'break'](http://hackage.haskell.org/package/base-4.9.0.0/docsがあります/Prelude.html#v:break)、これは一度行います。 'slice_when'の振る舞いを得るために再帰的にブレークを使用することはあまり難しいことではありませんが、それを実行する前奏関数はありません。確かに['split'](http://hackage.haskell.org/package/split-0.2.3.1/docs/Data-List-Split.html)パッケージに必要なものがあります。 – luqui

+1

おっと、わかりました、 'slice_when'はペアで動作します。これはもう少し複雑になります。 – luqui

答えて

5

は、ここで私はあなたのような作品が欲しいと考えていsliceWhen実装です:

sliceWhen :: (a -> a -> Bool) -> [a] -> [[a]] 
sliceWhen _ [] = [] 
sliceWhen _ [x] = [[x]] 
sliceWhen f (x:y:xs) 
    | f x y  = [x] : sliceWhen f (y:xs) 
    | otherwise = let z:zs = sliceWhen f (y:xs) 
       in (x:z) : zs 

上記の機能は、各境界に提供述語を実行し、それがTrueを返す場合、それは縫い目が作成されます。それ以外の場合は、現在の値を残りのリストの最初の要素に置きます。明示的な再帰なし

+0

これは非常にうまくいく、あなたの答えをありがとう。 ^。^ – Jesse

3

、およびNonEmptyを使用して:

import Data.List.NonEmpty 

sliceWhen :: (a -> a -> Bool) -> [a] -> [NonEmpty a] 
sliceWhen p = foldr f [] 
    where 
    f z [] = [z :| []] 
    f z [email protected]([email protected](x :| xs) : xss) = if p z x 
            then (z :| []) : gss 
            else cons z gs : xss 
+0

こんにちは、私は走って[1:| [2]、4:| []、9:| [10,11,12]、15:| [16]、19:|私はこの結果を理解できません。どうすればそれを[[1,2]、[4]、[9,10,11,12]に変換できますか? 、[15,16]、[19,20,21]]、私は初心者です、多くのありがとうございます。 – Jesse

+0

内側のNonEmptyの値は最初の要素とリストのペアとして表示されるので、奇妙に見えます。 [10,11,12] '。 'Prelude.map toList $ sliceWhen(\ xy - > x + 1/= y)[1,2,4,9,10,11,12]のように' map'を使って内側の値を通常のリストに変換することができます。 、15,16,19,20,21]。 – danidiaz