2014-02-23 64 views
1

我得到了这个项目做Im类型卡住了。我知道这不是太复杂,但我用完了想法。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 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

薄膜你能给我一些提示/指导吗?谢谢!

UPDATE:

感谢您的答复,而是因为我已经做了该项目的一半,我认为其后期更改数据类型,因为我不得不重新考虑一切。

我做了一个尝试,但它不工作的显示功能,我不知道为什么:

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)) 

UPDATE2:

我发现的脑杀小时后的溶液并发誓一切:)

再次感谢大家!

这:

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) 
+3

第一步:写一个函数':: Film - > [Rating]'来获得电影的所有等级。从这个角度来看,一个函数':: [评级] - >双',使平均。然后您可以查看提供的排序功能。 – progo

+2

查看'map'函数[here](http://hackage.haskell.org/package/base-4.6.0.1/docs/Prelude.html#v:map)和'sum :: Num a => [a] - > a'和'length :: [a] - > Int'函数。稍后,您需要'filter'函数[here](http://hackage.haskell.org/package/base-4.6.0.1/docs/Prelude.html#v:filter)来选择电影。您可以在[hoogle](http://www.haskell.org/hoogle/)上搜索功能。 – AndrewC

+0

您的'Mark'类型同义词不会在任何地方使用 - 您可能打算在定义'Rate'时使用它吗? –

回答

0

第一折:偏爱数据类型尽可能到元组+型同义词。如果要为现有类型指定不同的名称,则类型同义词很好,但定义自定义数据类型也会提供类型安全性,因此您不能只需使用任意元组而不是等级

所以你的数据类型将成为:

data Rating = Rating { ratingUsername :: String 
        , ratingStars :: Int 
        } 

data Film = Film { filmTitle :: String 
       , filmDirector :: String 
       , filmYear :: Int 
       , filmRatings :: [Rating] 
       } 

和你testDatabase:

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]的从电影分级。

一个很好的方法来解决这类问题是首先考虑所需要的类型注释,然后继续用hoogle

所以帮助这里计算的平均收视率实施这些都是你应该尝试的步骤:

  • 定义了一个函数来计算平均评分(你可能想看看例如foldl和朋友)

    averageStars :: [Rating] -> Double 
    
  • 过滤器的基础上评级的属性,然后你可以使用过滤用appropiate断言:

    filter :: (a -> Bool) -> [a] -> [a] 
    

    其中(a -> Bool)你的情况Film -> Bool所以你会写函数

    goodFilm :: Film -> Bool 
    

    并使用您之前定义的averageStars函数来比较评级是否为 足够高。

+0

我更新了第一篇文章!感谢您的回复! – Bobys