Reputation: 31
Well i've this movies (peliculas in spanish) so i need to groupby categories (Fiction,Scare,Drama,Suspense,Comedy,Action).
This is how my data movie looks like:
data Pelicula = Pelicula
{ _id :: Int
, _titulo :: String
, _alquilada :: Bool
, _videoclub :: V.VideoClub
, _categoria :: String
} deriving Show
The categories "Attribute" is a String, so if i've this list of movies:
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"
Movie list: peliculas = [pelicula1 , pelicula2, pelicula3, pelicula4, pelicula5, pelicula6, pelicula7, pelicula8, pelicula9, pelicula10]
1) How can i group them by the ficcion (Fiction) category? or Suspense?
2) How can i create a list of categories from the list of movies?
Upvotes: 0
Views: 83
Reputation: 48654
How can i group them by the ficcion (Fiction) category? or Suspense?
Haskell base has a groupBy
function which can be used for this purpose. You can see it's type in ghci
:
λ> import Data.List (groupBy)
λ> :t groupBy
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
Let me demonstrate that with a simpler example than your (you can use the same idea to adapt it to your code):
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
The groupFunction
will be what you will be using for performing the actual grouping. Demo in 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"}]]
You can adapt this to your use case.
Upvotes: 2
Reputation: 43310
The following code implements a utility function, which can be applied to your problem:
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]))
Using that function now you can group your data easily:
groupPeliculas :: [Pelicula] -> Map.Map String [Pelicula]
groupPeliculas =
groupToMap _categoria
Extracting a list of categories is not any less trivial:
peliculaCategories :: [Pelicula] -> [String]
peliculaCategories =
map _categoria
If you need to get a list of unique items, do it this way:
import qualified Data.List as List
peliculaCategories :: [Pelicula] -> [String]
peliculaCategories =
List.nub . map _categoria
But then it'll be smarter to use the Set
datastructure for that:
import qualified Data.Set as Set
peliculaCategories :: [Pelicula] -> Set.Set String
peliculaCategories =
foldr Set.insert Set.empty . map _categoria
Upvotes: 2