[英]Filter for element in a list of lists in Haskell
我建立了這個結構的清單:
[(Interger, Double)]
該列表是通過在整數列表和大小完全相同的Doubles列表上使用zip來創建的。
現在,我要過濾<18.5或> 25的雙打列表。 我的問題是我無法訪問Doubles在過濾器功能中使用它們。
這可能很簡單,但是我是這種語言中的流氓。 我在Google上搜索了很多,還讀了其他一些主題,但沒有找到答案。
我有:
filter (<18.5) listexpression
所以我正在努力的是listexpression。 如果它是單個值的列表,這很容易。 我可以在壓縮之前進行過濾,但是之后我無法再將數據從過濾列表連接到另一個未過濾列表。
編輯:我忘了提。 這是一個工作表。 我們被要求自己構建過濾器和映射函數,並且不允許對基本的Haskell使用任何附加功能。 表示不允許進口。
您可以執行以下操作:
Prelude> filter (\p -> (snd p) < 18.5 || (snd p) > 25) [(1, 2.3), (1, 20.0)]
[(1,2.3)]
傳遞給filter
的lambda函數 ,即
(\p -> (snd p) < 18.5 || (snd p) > 25)
說,對於每個p
,的第二個元素p
必須小於18.5或超過25。
或者,您可以這樣寫
Prelude> filter (\(_, f) -> f < 18.5 || f > 25) [(1, 2.3), (1, 20.0)]
[(1,2.3)]
這里的函數說,對於第一個值無關緊要而第二個值是f
任何一對, f
必須小於18.5或大於25。
很高興看到Ami Tavory的答案解決了您的問題。
但是在該答案下,您評論了:
我嘗試使用(!!)的組合來訪問它,但是沒有用。
憑着助教[:D]的見識,我想您將list
與Haskell中的tuple
混淆了。
zip
返回一個tuple
list
,而(!!)
將list
作為(第一個)參數(因此(!!1)
采用單個list
參數),因此(!!1)
不能應用於zip
返回的list
,其類型為tuple
。
Prelude> :t zip
zip :: [a] -> [b] -> [(a, b)]
Prelude> :t (!!)
(!!) :: [a] -> Int -> a
Prelude> :t (!!1)
(!!1) :: [a] -> a
並且您已經知道fst
和snd
應用於tuple
。
Prelude> :t fst
fst :: (a, b) -> a
Prelude> :t snd
snd :: (a, b) -> b
使用無點樣式的緊湊版本將是
filter ((>18.5).snd) listexpression
這使用函數組合運算符.
,其內容為:首先將snd
函數應用於列表中的元組以提取第二個值,然后將比較值18.5應用於此值。
只是為了提供各種內容和一些其他信息,這些信息將不會咬人。
在Haskell中,列表類型是Monad類的實例 。 因此,列表操作(例如filter
可以簡單地由monadic bind操作符實現。
*Main> [(1,2.3),(3,21.2),(5,17.1),(4,24.4)] >>= \t -> if snd t < 25 && snd t > 18.5 then [t] else []
[(3,21.2),(4,24.4)]
Monad就是以順序方式處理包含的數據。 在列表monad中,包含的數據是列表本身內的值。 因此,bind運算符可以非常方便地按順序訪問單子值(元組列表)的包含值(元組)。
(>>=) :: Monad m => m a -> (a -> m b) -> m b
monadic綁定運算符的類型簽名指出,它將monad類型值ma
作為第一個參數(此處為元組列表),將函數用作第二個參數,該函數采用純值並返回monadic值(采用元組和返回列表中的元組或在這種情況下返回空列表)。
\t -> if snd t < 25 && snd t > 18.5 then [t] else []
了解如何以及為什么將列表項一一應用於所提供的功能至關重要。 整個列表是一個Monadic值,綁定操作符訪問的包含值將傳遞給提供a -> mb
(采用純值並返回Monadic值)類型的函數。 因此,所有應用於此函數的列表項都變為單子值(如果條件滿足,則為[t]
如果條件失敗,則為[]
),然后由bind運算符連接起來以形成一個單子返回值(在這種情況下,列表為滿足lambda函數中實現的條件的元組)。
此monadic操作也可以使用do
表示法實現
do
t <- [(1,2.3),(3,21.2),(5,17.1),(4,24.4)]
if snd t < 25 && snd t > 18.5 then return t else []
[(3,21.2),(4,24.4)]
當然,這完全類似於列表理解,實際上是單子列表操作的語法糖。 因此,讓我們使用列表推導在最后一次實現它。
*Main> [t | t <- [(1,2.3),(3,21.2),(5,17.1),(4,24.4)], snd t < 25 && snd t > 18.5]
[(3,21.2),(4,24.4)]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.