簡體   English   中英

在Haskell的列表列表中過濾元素

[英]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)]

傳遞給filterlambda函數 ,即

(\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

並且您已經知道fstsnd應用於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM