2014-02-23 63 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