2016-04-19 7 views
3

値が増加している間に私が取りたい値の一覧があります。私はそれが常にリストの先頭をとり、それを次の値と比較すると仮定します。これが増え続ける限り、この機能は引き続き使用されます。以前の値以下のリスト要素に到達すると、リストが返されます。増加中のリストから取り除く

takeIncreasing :: (Ord a) => [a] -> [a] 
takeIncreasing [1,2,3,4,3,5,6,7,8] -- Should return [1,2,3,4] 

倍は次の値と蓄積のlast要素を比較し、条件が満たされた場合に追加しますが、リストの最後まで続けることができます。私は制約が満たされていない最初のインスタンスを取ることを止める機能を望みます。

これはモナドのアプリケーションのようですが、既存のモナドがこれを達成するかどうかを判断することはできません。

答えて

8

折りたたみ[...]はリストの最後まで続きます。私は制約が満たされていない最初のインスタンスを取ることを止める機能を望みます。

右の倍は短絡することができます:

fun :: Ord a => [a] -> [a] 
fun []  = [] 
fun (x:xs) = x: foldr go (const []) xs x 
    where go x f i = if i < x then x: f x else [] 

はその後、

\> fun [1,2,3,4,3,undefined] 
[1,2,3,4] 

または無限サイズのリスト:

\> fun $ [1,2,3,4,3] ++ [1..] 
[1,2,3,4] 
+0

Nitpick:右折は、ハスケルのような低速評価言語**で短絡する可能性があります。しかし、これはもちろん、知ることは非常に重要なポイントです!ハスケルに来る多くの人々は、熱心に評価された言語の経験を持っています。彼らは(a)リストの最後まで続き、(b)長いリストにスタックを吹き飛ばすので、右折はしばしば逃げます。しかし、Haskellの 'foldr'はその問題を持たない方法でよく使われています。実際、Haskellの' foldl'はスタックを吹き飛ばす危険があります! –

4

右折り目は魔法されているので、あなたは、決しても、リストのパターンマッチングが必要です。折り返しのない

twi xs = foldr go (const []) xs Nothing where 
    go x _ (Just prev) 
    | x < prev = [] 
    go x r _ = x : r (Just x) 
2

ソリューション :

takeIncreasing :: Ord a => [a] -> [a] 
takeIncreasing [] = [] 
takeIncreasing (x:xs) = (x :) . map snd . takeWhile (uncurry (<)) $ zip (x:xs) xs 
3

またはIMOビット少ないコードの複雑さを持っている1:

takeIncreasing :: Ord x => [x] -> [x] 
takeIncreasing (x:x':xs) | x < x' = x : takeIncreasing (x':xs) 
         | otherwise = [x] 
takeIncreasing xs = xs 

この1つは、以前の提案よりも少しだけ小さい賢いです。私は賢いコードが好きです。

関連する問題