Nathan Edwards
Nathan Edwards

Reputation: 311

Filter based on the output of a filter

I have a list of lists, e.g. [[1,1,3],[1,2,4],[4,4,4],[5,6,7]]

I want to remove all lists with duplicate elements, returning e.g. [[1,2,4],[5,6,7]]

My current problem is in creating a predicate for my application of filter. I'm currently attempting to test the length of a filtered list against expected length of that list. However, I'm struggling to get it to work as a function on the elements of list.

removeLoops :: [[Integer]] -> Integer -> [[Integer]]
removeLoops list vs = filter (genericLength(filter (==)) < vs) list

Am I barking up the wrong tree? Or just a misunderstanding of predicates?

Upvotes: 1

Views: 86

Answers (2)

Boris
Boris

Reputation: 5176

I think the solution is simpler than you think. You could filter your list with a predicate that tests whether a given list has duplicates:

ls = [[1,1,3],[1,2,4],[4,4,4],[5,6,7]]
filtered = filter hasNoDuplicates ls

Then all that remains is to find a suitable predicate. In this instance, the nub function comes in handy. This function takes a list, and returns that list without duplicates. So you could say:

import Data.List (nub)

hasNoDuplicates l = l == nub l

Upvotes: 3

Karolis Juodelė
Karolis Juodelė

Reputation: 3770

This should work for you.

removeListsWithDuplicates ues a helper hasDuplicates to filter the list of lists. Simple.

removeListsWithDuplicates :: [[Integer]] -> [[Integer]]
removeListsWithDuplicates ls = filter (not . hasDuplicates) ls

hasDuplicates. An empty list has no duplicates. A list with several elements only has duplicates if the first one is repeated in the rest of the list or if the rest of the list has some other duplicates.

hasDuplicates :: [Integer] -> Bool
hasDuplicates [] = False
hasDuplicates (x:xs) = any (==x) xs || hasDuplicates xs

Upvotes: 2

Related Questions