Home > Back-end >  Filter a list of tuples in Haskell
Filter a list of tuples in Haskell

Time:02-25

I'm pretty new to Haskell and I'm trying to filter a list of tuples that contain a string and a list of strings. I want to filter based on if the list of strings contains a certain string. I'd like to create a list of lists where each list is the first element of every tuple that evaluates to true for the filter.

Example:
Given this list of tuples
progLanguages =
[ ("CptS121" , ["C"]),
("CptS122" , ["C "]),
("CptS223" , ["C "]),
("CptS233" , ["Java"]),
("CptS321" , ["C#","Java"]),
("CptS322" , ["Python","JavaScript"]),
("CptS355" , ["Haskell", "Python", "PostScript", "Java"]),
("CptS360" , ["C"]),
("CptS370" , ["Java"]),
("CptS315" , ["Python"]),
("CptS411" , ["C", "C "]),
("CptS451" , ["Python", "C#", "SQL","Java"]),
("CptS475" , ["Python", "R"])
]

I want to filter the tuples that contain ["Python","C","C "] and create a list of lists where each sub list is the courses that uses each language.

So, ["Python","C","C "] would output [ ["CptS322","CptS355","CptS315","CptS451","CptS475"], ["CptS121","CptS360","CptS411"], ["CptS122","CptS223","CptS411"] ]

So far I have the following:

    filter_courses [] courses = []
    filter_courses list [] = []
    filter_courses list courses = map snd (filter ((`elem` courses).fst) list)

This filters progLanguages and outputs a list of all the tuples that use any of the listed languages in 'courses'.

Taking the output from the above list, im trying to do the following...

    filter_more [] langs = []
    filter_more list [] = []
    filter_more list langs = map fst (filter ((`elem` langs).snd) list)

This outputs a list of all the courses that use any of the languages instead of a list of courses for each language.

CodePudding user response:

How about the following:

progLanguages = [ ("CptS121", ["C"])
                , ("CptS122", ["C  "])
                , ("CptS223", ["C  "])
                , ("CptS233", ["Java"])
                , ("CptS321", ["C#","Java"])
                , ("CptS322", ["Python","JavaScript"])
                , ("CptS355", ["Haskell", "Python", "PostScript", "Java"])
                , ("CptS360", ["C"])
                , ("CptS370", ["Java"])
                , ("CptS315", ["Python"])
                , ("CptS411", ["C", "C  "])
                , ("CptS451", ["Python", "C#", "SQL","Java"])
                , ("CptS475", ["Python", "R"])
                ]

filterCourses :: Eq a => [a] -> [(b, [a])] -> [[b]]
filterCourses langs courses = map coursesUsing langs
  where coursesUsing lang = map fst . filter (elem lang . snd) $ courses

main = do
  print $ filterCourses [] progLanguages
-- []
  print $ filterCourses ["Python","C","C  "] progLanguages
-- [["CptS322","CptS355","CptS315","CptS451","CptS475"],["CptS121","CptS360","CptS411"],["CptS122","CptS223","CptS411"]]

I split the task into two steps: first, I made a function coursesUsing that lists the courses given a language. Then I applied the function to each language using map.

Or, using list comprehension:

filterCourses langs courses = [[course | (course, langs) <- courses, lang `elem` langs] | lang <- langs]
  • Related