列表中的Haskell平均值
我要做这个项目,我有点卡住了。我知道这不是很复杂,但我已经没有主意了 我定义了这些类型:列表中的Haskell平均值,haskell,Haskell,我要做这个项目,我有点卡住了。我知道这不是很复杂,但我已经没有主意了 我定义了这些类型: -- Types type Title = String type Director = String type Year = Int type Mark = Int type Rating = (String, Int) -- Define Film type here type Film = (Title, Director, Year, [Rating]) -- Define database
-- Types
type Title = String
type Director = String
type Year = Int
type Mark = Int
type Rating = (String, Int)
-- Define Film type here
type Film = (Title, Director, Year, [Rating])
-- Define database type here
type Database = [Film]
testDatabase :: [Film]
testDatabase =
[("Casino Royale", "Martin Campbell", 2006, [("Garry",8),("Dave", 0)])
,("Blade Runner", "Ridley Scott", 1982, [("Amy",5),("Dave", 9]),
,("The Fly", "David Cronenberg", 1986, [("Fred",7),("Dave", 4)])
]
所以现在我必须显示平均评级,然后我必须显示平均评级等于或高于6的电影
你能给我一些提示/指导吗?谢谢
更新:
谢谢你的回复,但是因为我已经完成了项目的一半,我认为更改数据类型太晚了,因为我必须重新考虑所有事情
我尝试过,但显示功能不起作用,我不知道为什么:
filmRating :: [Rating] -> Int
filmRating rating = div (sum [r | (_,r) <- rating]) (length rating)
averageFilm :: Film -> Int
averageFilm (t, d, y, r) = filmRating r
sixOrHigher :: Int -> Bool
sixOrHigher average
| average <= 6 = True
| otherwise = False
displayAverage :: Database -> String
displayAverage database = displayFilms (filter ((sixOrHigher (averageFilm)) database))
filmRating::[Rating]->Int
电影评级=div(和[r |(u,r)Int
平均胶片(t,d,y,r)=胶片评级r
六或更高::整数->布尔
六个或更高的平均值
|平均字符串
displayAverage数据库=displayFilms(过滤器((六个或更高的(averageFilm))数据库))
更新2:
经过数小时的脑残和咒骂,我找到了解决办法:)
再次感谢大家
这是:
averageFilm :: Film -> Int
averageFilm (t, d, y, r) = filmRating r
averageFilms :: Database -> [Int]
averageFilms database = map (averageFilm) database
sixOrHigher :: Int -> Bool
sixOrHigher average
| average <= 6 = True
| otherwise = False
checkAllIfHigher :: Film -> Bool
checkAllIfHigher film = (sixOrHigher (averageFilm film))
displayAverage :: Database -> String
displayAverage database = displayFilmsAverage (filter (checkAllIfHigher) database)
displayFilmsAverage :: Database -> String
displayFilmsAverage database = concat(map (displayFilmAverage ) database)
averageFilm::Film->Int
平均胶片(t,d,y,r)=胶片评级r
averageFilms::数据库->[Int]
averageFilms数据库=地图(averageFilm)数据库
六或更高::整数->布尔
六个或更高的平均值
|平均布尔
检查所有高胶片=(六张或更高(平均胶片))
displayAverage::数据库->字符串
displayAverage database=displayFilmsAverage(筛选(checkAllIfHigher)数据库)
displayFilmsAverage::数据库->字符串
displayFilmsAverage数据库=concat(地图(displayFilmAverage)数据库)
首先:尽可能选择数据类型而不是元组+类型同义词。如果您希望为现有类型指定不同的名称,则类型同义词很好,但定义自定义数据类型也可以提供类型安全性,因此您不能简单地使用任何元组而不是评级
因此,您的数据类型将变成:
data Rating = Rating { ratingUsername :: String
, ratingStars :: Int
}
data Film = Film { filmTitle :: String
, filmDirector :: String
, filmYear :: Int
, filmRatings :: [Rating]
}
以及您的测试数据库:
testDatabase :: [Film]
testDatabase = [ Film "Casino Royale" "Martin Campbell" 2006
[Rating "Garry" 8, Rating "Dave" 0]
, Film "Blade Runner" "Ridley Scott" 1982
[Rating "Amy" 5, Rating "Dave" 9]
, Film "The Fly" "David Cronenberg" 1986
[Rating "Fred" 7, Rating "Dave" 4]
]
使用我们的新数据类型,我们可以通过filmRatings::film->[Rating]
仅选择影片的收视率
解决这类问题的一个好方法是首先考虑所需的类型注释,然后在
因此,要计算平均评分,请尝试以下步骤:
- 定义一个函数来计算平均评分(您可能希望查看例如
和朋友)foldl
- 若要基于评级的属性进行筛选,则可以使用具有适当谓词的筛选器:
其中filter :: (a -> Bool) -> [a] -> [a]
在您的例子中是(a->Bool)
,因此您可以编写一个函数Film->Bool
并使用之前定义的averageStars函数比较评级是否足够高goodFilm :: Film -> Bool
::Film->[Rating]
,获取一部电影的所有评级。然后,一个函数::[Rating]->Double
进行平均。然后您可以查看提供的排序函数。查看map
函数和sum::Num a=>[a]->a
和长度::[a]->Int
函数。稍后您需要使用过滤器
函数来选择影片。您可以在上搜索函数。您的标记
类型同义词没有在任何地方使用-可能您是想在定义速率
时使用它?
goodFilm :: Film -> Bool