简体   繁体   English

对列表中的项目使用过滤器?

[英]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". 它应该是相当不言自明的,您可以使用letwhere语句来定义“局部变量”。 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
  • and so forth 等等

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM