Haskellのリストの最後の要素を取得する最速の方法は何ですか。また、次の反復では、リストの最初と最後の要素を削除します。最もエレガントな方法は何ですか?リストの理解を試みていますが、それはあまり効率的ではありません!
last
とinit
は、1回限りの仕事をうまく行います。ただし、両方ともO(n)なので、リストの両端を頻繁に操作する必要がある場合は、暗黙のように思われるかもしれませんが、 Data.Sequence
代わりに、O(1)両端のアイテムの挿入と削除をサポートします。
last
関数 を使用して、リストの最後の要素を取得できます。
最初と最後の要素を削除する方法については、(init . tail)
、しかしそれがどれほど効率的かはわかりません。
Learn You A Haskell のこの画像は、リスト関数をかなりよく示していると思います。
Preludeの実装はまだ投稿されていないので投稿します。
_listLast :: [a] -> a
listLast [x] = x --base case is when there's just one element remaining
listLast (_:xs) = listLast xs --if there's anything in the head, continue until there's one element left
listLast [] = error "Can't do last of an empty list!"
_
関数名をlistLast
に変更したため、通常のPreludeと競合することなく実行できることに注意してください。もちろん、import Prelude hiding(last)
を実行できます。
この答えは、(空のリストのような)奇妙な条件を最大限に柔軟な方法で処理し、いくつかのライブラリ関数を使用して小さな関数から大きな関数を構築することに焦点を当てています。それはnotで、リストについて最初に学習した人にとっては最良の答えですが、それよりも数ステップ先です。
以下のために、あなたは必要になります
_import Control.Monad ((>=>))
_
gHC 7.10を使用してData.List (uncons)
をインポートするか、定義する必要があります
_uncons :: [a] -> Maybe (a, [a])
uncons [] = Nothing
uncons (x:xs) = Just (x,xs)
_
次のような安全な形式のinit
を書くことができます:
_init' :: [x] -> Maybe [x]
init' = foldr go Nothing
where
go x mxs = Just (maybe [] (x:) mxs)
_
tail
のバージョンを書くことができます
_tail' :: [a] -> Maybe [a]
tail' = fmap snd . uncons
_
だからあなたは多分得ることができます
_trim' :: [a] -> Maybe [a]
trim' = init' >=> tail'
_
_>=>
_は、一種の後方モナド合成です。 _init' >=> tail'
_は、_init'
_を引数に適用して_Maybe [a]
_を取得する関数です。 Nothing
を取得すると、それを返します。 _Just xs
_を取得した場合、xs
に_tail'
_を適用し、それを返します。
これから、0、1、または2要素のリストを空のリストにトリムするトリマーを簡単に作成できます。
_trim :: [a] -> [a]
trim = maybe [] id . trim'
_
最初と最後を削除するには:
take (len(l)-2) (drop 1 l)
または多分
init (drop 1 l)
これにより、ほぼ最適なコードも生成されます。