2013-10-26 5 views
5

インターレース要素を分離する関数を書いた。1つのループでインターレース要素を分離する

interlacedElems :: [a] -> ([a], [a]) 
interlacedElems xs = (f xs, f $ tail xs) 
    where f (x:_:xs) = x : f xs 
     f x = x 

main = print $ interlacedElems "a1b2c3d4" 

生成出力:私のコードで

("abcd","1234") 

私は効果的に二回が、わずかに異なり、同じリストを毎回再帰、fを定義し、それを2回使用しています。

私の質問は:私はこれを書くことができる方法はありますか?それはより効率的なので、あなたは馬鹿だと思いませんか?

脳の一部が漏出してしまったのを見てみると、私はいつも脳のジュースが全部あふれていると言い、お母さんは私に言いました。カーペット。

はあなたに素敵な人たちに感謝:)

+0

これに対処したいだけです:「それが効率的なので、あなたは思いませんか?」。私の推測は「おそらく本当にない」と思われますが、それがあなたにとって重要なものかどうかを正確に測定すべきです!チェックアウト[基準](http://hackage.haskell.org/package/criterion)またはそれのようなもの。 –

答えて

2

私は再帰的タプルにリストを分割する関数を記述し、その後unzipを使用します。

listToTuples :: [a] -> [(a, a)] 
listToTuples (x:y:xs) = (x, y) : listToTuples xs 
listToTuples _ = [] 

interlacedElems :: [a] -> ([a], [a]) 
interlacedElems = unzip . listToTuples 
+0

'unzip'アルゴリズムと明示的再帰アルゴリズムの両方が〜n/2ステップを要しますので、より効率的な方法でOPの要求にマッチします。唯一の可能性のある問題は、元のリストに奇数の要素がある場合、最後の要素は破棄されます。 – duplode

+0

@duplode私はそれを考えましたが、戻り値の型が '([(a、a)]、おそらくa)'以外の問題を解決する良い方法はないと思います。最後の要素が必要です。 – bheklilr

9

ます。また、それはこのトリックを使用してfoldrを使用して行うことができます。

interlacedElems :: [a] -> ([a], [a]) 
interlacedElems = foldr (\x ~(l,r) -> (x:r,l)) ([],[]) 

反駁可能なパターン~(l,r)は、無限リストに作用します。

+0

ニート。唯一の注意点は、どのサブリストが元のリストの最初の要素で終わるかが重要な場合は、サブリストにタグを付ける必要があるということです。 – duplode

+1

@duplode最初の要素は常にペアの最初のリストで終わることは簡単に証明できます。 – is7s

+0

確かに。申し訳ありませんが、それは愚かな間違いでした。 – duplode

関連する問題