如何在haskell中分组类别?

时间:2015-09-27 18:01:00

标签: haskell

我有这部电影(西班牙语的peliculas)所以我需要分组(小说,恐慌,戏剧,悬疑,喜剧,动作)。

这就是我的数据电影的样子:

data Pelicula = Pelicula
  { _id          :: Int
  , _titulo      :: String
  , _alquilada   :: Bool
  , _videoclub   :: V.VideoClub
  , _categoria   :: String
  } deriving Show

类别“属性”是一个字符串,所以如果我有这个电影列表:

pelicula1  = Pelicula 1   "Inception"                         True      V.videoclub1      "Ficcion"
pelicula2  = Pelicula 2   "Inception"                         True      V.videoclub2      "Ficcion"
pelicula3  = Pelicula 3   "Inception"                         True      V.videoclub1      "Ficcion"
pelicula4  = Pelicula 4   "The Call"                          True      V.videoclub1      "Miedo"
pelicula5  = Pelicula 5   "Frozen"                            True      V.videoclub2      "Fantasia"
pelicula6  = Pelicula 6   "Fight Club"                        False     V.videoclub2      "Accion"
pelicula7  = Pelicula 7   "Now you see me"                    False     V.videoclub1      "Suspenso"
pelicula8  = Pelicula 8   "Frozen"                            False     V.videoclub1      "Fantasia"
pelicula9  = Pelicula 9   "The Call"                          False     V.videoclub2      "Miedo"
pelicula10 = Pelicula 10  "Up"                                True      V.videoclub2      "Fantasia"

电影列表:peliculas = [pelicula1 , pelicula2, pelicula3, pelicula4, pelicula5, pelicula6, pelicula7, pelicula8, pelicula9, pelicula10]

1)我如何通过ficcion(Fiction)类别对它们进行分组? 还是悬念?

2)如何从电影列表中创建类别列表?

2 个答案:

答案 0 :(得分:2)

以下代码实现了一个实用程序功能,可以应用于您的问题:

import qualified Data.Map as Map -- from the "containers" library

groupToMap :: (Ord b) => (a -> b) -> [a] -> Map.Map b [a]
groupToMap toKey =
  Map.fromListWith (++) . map (\a -> (toKey a, [a]))

现在使用该功能,您可以轻松地对数据进行分组:

groupPeliculas :: [Pelicula] -> Map.Map String [Pelicula]
groupPeliculas =
  groupToMap _categoria

提取类别列表并不是那么简单:

peliculaCategories :: [Pelicula] -> [String]
peliculaCategories =
  map _categoria

如果您需要获取唯一项目列表,请按以下方式执行:

import qualified Data.List as List

peliculaCategories :: [Pelicula] -> [String]
peliculaCategories =
  List.nub . map _categoria

但是那时使用Set数据结构会更聪明:

import qualified Data.Set as Set

peliculaCategories :: [Pelicula] -> Set.Set String
peliculaCategories =
  foldr Set.insert Set.empty . map _categoria

答案 1 :(得分:2)

  

我如何通过ficcion(Fiction)类别分组?还是悬念?

Haskell base具有groupBy函数,可用于此目的。您可以在ghci中看到它的类型:

λ> import Data.List (groupBy)
λ> :t groupBy
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]

让我演示一个比你更简单的例子(你可以用同样的想法让它适应你的代码):

data Test = Test { id :: Int,
                   someField :: String 
                 } deriving (Eq, Show, Ord)

sampleData = [Test 1 "hello", Test 2 "World", Test 3 "hello", Test 4 "World"]

groupFunction :: Test -> Test -> Bool
groupFunction t1 t2 = someField t1 == someField t2

groupFunction将用于执行实际分组。 ghci中的演示:

λ> groupBy groupFunction $ sortBy (\x y -> someField x `compare` someField y) sampleData 
[[Test {id = 2, someField = "World"},Test {id = 4, someField = "World"}],[Test {id = 1, someField = "hello"},Test {id = 3, someField = "hello"}]]

您可以根据您的使用情况进行调整。