[英]Using filter on an item in a list?
I am trying to filter by an item in a list and print them line by line. 我试图按列表中的项目进行过滤并逐行打印。 Here's my code: 这是我的代码:
data Car = Car String [String] Int [String]
testDatabase :: [Car]
testDatabase = [Car"Casino Royale" ["Daniel Craig"] 2006 ["Garry", "Dave", "Zoe", "Kevin", "Emma"],Car"Blade Runner" ["Harrison Ford", "Rutger Hauer"] 1982 ["Dave", "Zoe", "Amy", "Bill", "Ian", "Kevin", "Emma", "Sam", "Megan"]]
formatCarRow (Car a b c d) = show a ++ " | " ++ concat [i ++ ", " | i <- init b] ++ last b ++ " | " ++ show c ++ " | " ++ concat [j ++ ", " | j <- init d] ++ last d
displayFilmsByYear :: String -> IO [()]
displayFilmsByYear chosenYear = mapM (putStrLn.formatFilmRow) [putStrLn(filter ((== chosenYear).y)) | (w x y z) <- testDatabase] -- This is the code not working i think
Why isnt this working? 为什么这不起作用?
If you wish to filter a list, I recommend using the filter
function :) 如果你想过滤列表,我建议使用filter
功能:)
data Car = Car String [String] Int [String]
year :: Car -> Int
year (Car _ _ y _) = y
filterByYear :: Int -> [Car] -> [Car]
filterByYear chosenYear cars = filter (\car -> year car == chosenYear) cars
showCar :: Car -> String
showCar car = undefined -- you can implement this how you like
displayCarsByYear :: Int -> IO ()
displayCarsByYear chosenYear = mapM_ (putStrLn . showCar) filteredCars
where filteredCars = filterByYear chosenYear testDatabase
It seems wise to explain a few things here: 在这里解释一些事情似乎是明智的:
Anonymous Functions : (\\car -> year car == chosenYear)
is an anonymous function. 匿名函数 : (\\car -> year car == chosenYear)
是一个匿名函数。 It takes one argument and calls it car
. 它需要一个参数并称之为car
。 Then it determines whether that car's year is equal to the chosenYear
. 然后它确定该汽车的年份是否等于所选择的chosenYear
。 I didn't explicitly write this function's type signature, but it's Car -> Bool
. 我没有明确写出这个函数的类型签名,但它是Car -> Bool
。
Filtering : I gave that function to filter
, so that it would look through the list of Car
s. 过滤 :我给了该函数进行filter
,以便它可以查看Car
的列表。 When filter
finds cars for which that function returns True
, it puts them in the result list. 当filter
找到该函数返回True
汽车时,它会将它们放入结果列表中。 A False
result means that a car doesn't make it through the filter. False
结果意味着汽车没有通过过滤器。
Function composition : (putStrLn . showCar)
This is a function that first performs showCar
, and then uses putStrLn
on the result of showCar
. 函数组成 : (putStrLn . showCar)
这是一个首先执行showCar
的函数,然后在putStrLn
的结果上使用showCar
。
Where : You'll notice the where
statement at the end of my code. Where :您会注意到我的代码末尾的where
语句。 It should be fairly self-explanatory, you can use either let
or where
statements to define "local variables". 它应该是相当不言自明的,您可以使用let
或where
语句来定义“局部变量”。 As a matter of taste, I prefer where over let. 作为一个品味问题,我更喜欢在哪里过度。
List comprenensions vs filter : List comprehensions can filter a list just like the filter function. 列出comprenensions与过滤器 : 列表推导可以像过滤器功能一样过滤列表。 For a function f :: a -> Bool
, and a list xs :: [a]
对于函数f :: a -> Bool
,以及列表xs :: [a]
filter f xs
is the same as [x | x <- xs, fx]
filter f xs
与[x | x <- xs, fx]
相同 [x | x <- xs, fx]
. [x | x <- xs, fx]
。 As a matter of taste, I prefer spelling out filter
in such cases, since it makes it very clear that I'm filtering the list. 作为一个品味问题,我更喜欢在这种情况下拼写出filter
,因为它很清楚我正在过滤列表。
See also LYAH # Maps and filters 另请参阅LYAH#Maps和过滤器
-- -
Further recommendation: use record syntax 进一步建议:使用记录语法
Instead of 代替
data Car = Car String [String] Int [String]
Why not 为什么不
data Film = Film { name :: String
, actors :: [String]
, released :: Int
, characters :: [String]
}
(I couldn't really tell what your last list of Strings was) (我真的不知道你的最后一个字符串列表是什么)
This way, you can construct a Film like this: 这样,你可以构建一个像这样的电影:
lotr :: Film
lotr = Film { name = "Lord of the Rings"
, actors = ["Elijah Wood", "Ian McKellen", "Orlando Bloom"]
, released = 2001
, characters = ["Frodo", "Sam", "Pippin", "Merry"]
}
And you automatically have accessor functions 并且您自动拥有访问者功能
released :: Film -> Int
name :: Film -> String
See also LYAH # Record syntax 另请参阅LYAH #Record语法
The point is this: 关键在于:
[putStrLn(filter ((== chosenYear).y)) | (w x y z) <- testDatabase]
You haven't understood list comprehension yet. 你还没有理解列表理解。 What you want is: 你想要的是:
[ (Car w x y z) | (Car w x y z) <- testDatabase, y==choosenYear]
Probably. 大概。
With 同
mapM (putStrLn . formatCarRow)
you have already ordered: format and then print each element of the follwoing list . 你已经订购: 格式化然后打印下面列表的每个元素 。 Hence, the putStrLn in the list comprehension is utterly absurd. 因此,列表理解中的putStrLn是完全荒谬的。
Please note that putStrLn is in some way a misnomer: It won't print anything actually! 请注意,putStrLn在某种程度上用词不当:它实际上不会打印任何东西! It just constructs a thing that happens to cause printing when executed in the IO monad. 它只是构造了一个在IO monad中执行时会导致打印的事情。 It seems like this is hard to understand, but soon you will. 这似乎很难理解,但很快就会有。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.