所以我有一個從 3 到 10 的數字串列。我想得到最后一個大于 5 且小于 11 的數字。
*Main> greatestIndexInRange [3, 6, 7, 2, 5, 1, 0, 10, 2] 5 11
uj5u.com熱心網友回復:
您可以通過謂詞列出串列并在線性時間內選擇結果串列reverse(這將是原始串列中的最后一個元素)。或者您可以選擇過濾串列中的元素。filterheadlast
greatestIndexInRange :: Ord a => [a] -> a -> a -> a
greatestIndexInRange xs l h = head . filter (\x -> x > l && x < h) . reverse $ xs
greatestIndexInRange :: Ord a => [a] -> a -> a -> a
greatestIndexInRange xs l h = last $ filter (\x -> x > l && x < h) xs
例如:
greatestIndexInRange [3, 6, 7, 2, 5, 1, 0, 10, 2] 5 11
-- 10
請注意,如果串列中沒有元素在給定范圍內,這是一個部分函式,??它將失敗,例如:
greatestIndexInRange [1, 2, 3] 5 11
*** Exception: Prelude.head: empty list
正如 Chris 在評論中建議的那樣,您也可以在反向串列中使用findfromData.List而不是filter head以獲得更優雅的實作:
import Data.List (find)
greatestIndexInRange :: Ord a => [a] -> a -> a -> Maybe a
greatestIndexInRange xs l h = find (\x -> x > l && x < h) . reverse $ xs
該函式現在回傳一個Maybe. 這也將解決上述它是部分功能的問題:
greatestIndexInRange [3, 6, 7, 2, 5, 1, 0, 10, 2] 5 11
-- Just 10
greatestIndexInRange [1, 2, 3] 5 11
-- Nothing
uj5u.com熱心網友回復:
這將讓您在 GHC 9.2 或更高版本上執行您想要的操作:
{-# LANGUAGE ImpredicativeTypes #-}
import Control.Monad
import Data.Functor.Identity
lastJust :: forall f a b. Foldable f => (a -> Maybe b) -> f a -> Maybe b
lastJust p xs = foldr go id xs Nothing where
go :: a -> (forall t. Applicative t => t b -> t b) -> forall t. Applicative t => t b -> t b
go x acc z = maybe (acc z) (pure . runIdentity . acc . Identity) $ p x
greatestIndexInRange :: (Foldable t, Ord a) => t a -> a -> a -> Maybe a
greatestIndexInRange xs lo hi = lastJust (\x -> x <$ guard (x > lo && x < hi)) xs
uj5u.com熱心網友回復:
您可能希望選擇使用filterwith 而last不是使用reversewith find。更好的解決方案取決于以下因素:我們想要的元素在串列中的位置,串列中有多少與我們的謂詞匹配的元素等。您可能會根據具體情況決定,但任何一種解決方案都是美好的!
例如,如果我們想要的元素是 one 并且在開頭,肯定將其反轉并使用find比使用filterwith更糟糕last。同樣,如果我們有很多與我們的謂詞匹配的元素,并且filter均勻分布在整個串列中,那么最好反轉串列并使用find.
將結果包裝在 aMaybe中是明智的,以防萬一。這個想法是你需要以某種方式到達串列的末尾。所以無論哪種方式,你都不會得到比線性時間更好的解決方案,除非串列是有序的,在這種情況下你可以進行二進制搜索。
import Data.List
greatestIndexInRange :: Ord a => [a] -> a -> a -> Maybe a
greatestIndexInRange xs x y = find (\z -> z > x && z < y) (reverse xs)
輸出:
*Main Data.List> greatestIndexInRange [3, 6, 7, 2, 5, 1, 0, 10, 2] 5 11
Just 10
*Main Data.List> greatestIndexInRange [1, 2, 3] 5 11
Nothing
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/497527.html
標籤:哈斯克尔
