降序列表的排序

时间:2014-02-25 19:14:33

标签: sorting haskell

我试图根据平均评分对列表进行排序。我设法创建一个函数来返回平均评级和函数来过滤数据库并返回给定年份的电影。 但是我如何将所有这些放在一起并获得排序的输出?你能给我一些提示吗?

我的代码是:

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

-- These 2 functions are for the average rating

averageFilm :: Film -> Float
averageFilm (t, d, y, r) = averageFilmRating r

averageFilmRating :: [Rating] -> Float
averageFilmRating rating = fromIntegral ((sum [r | (_,r) <- rating])) / fromIntegral ((length rating))

---- These 2 functions are for the year filtering

displayFilmsYear :: Year -> Database -> String
displayFilmsYear year database = displayFilms (filter (filmYear year) database)

filmYear :: Year -> Film -> Bool
filmYear year (t, c, y, f)
         | year <= y = True
     | otherwise = False 

1 个答案:

答案 0 :(得分:5)

import Data.List
import Data.Ord

sortByRating :: [Film] -> [Film]
sortByRating = sortBy (flip $ comparing averageFilm)

sortBy允许您使用给定的比较函数对列表进行排序。此函数具有类型

(a -> a -> Ordering)

其中Ordering表示第一个参数是否小于,大于或等于第一个参数。

sortBy :: (a -> a -> Ordering) -> [a] -> [a]

对于您的Film列表,您的比较函数的类型为Film -> Film -> Ordering。您可以创建这样的功能 与comparing

comparing :: Ord a => (b -> a) -> (b -> b -> Ordering)

在你的情况下,你需要返回序数值来比较电影。你已经拥有了这样一个功能 - averageFilm。因此,comparing averageFilm会返回一个函数(Film -> Film -> Ordering),用于比较两部影片的评分。

sortBy (comparing averageFilm)将按等级按升序对列表进行排序,因此要按降序排序,您只需将参数的顺序翻转到比较函数,即flip (comparing averageFilm)