Imagine a nested list as below.
["A","ABBA","ABABA"]
I would like to create a function which 开发者_运维问答removes singleton elements from this list (in this example, "A"), and removes any lists containing that singleton element.
So that:
removeElems ["A","ABBA","CCC"] -> ["CCC"]
Below is my attempt at solving this problem:
badElements nested = concat $ filter (\c -> length c == 1) nested
removeElements nested = [c | c <- nested, u <- badElements nested, not $ any (==u) c]
This produces strange results where the multiple generators 'cycle' the nested list, such as below:
["A","ABBA","C","BCCB"] --> ["A","A","ABBA","ABBA","C","C","BCCB","BCCB"]--> ["A","ABBA","C","BCCB"]
Another example:
[[1],[1,2,3,4],[2],[5,6,7,8]] --> [5,6,7,8]
Since you only want to produce zero or one outputs for each list element, you don't want a list comprehension that iterates over badElements
. Instead, you want to filter on a predicate that iterates over badElements
.
What predicate? Well, a list is good if it doesn't contain a bad element. That is, all of its elements are not bad.
removeElements nested = filter (all (`notElem` badElements nested)) nested
Here's an untested attempt at it:
removeElements ls = filter (null . intersect singletons) ls
where singletons = mapMaybe singleElem ls
singleElem [x] = Just x
singleElem _ = Nothing
Another attempt:
badElements :: [[a]] -> [a]
badElements = concat . filter (\x -> 1 == length x)
removeBadElements :: (Eq a) => [[a]] -> [[a]]
removeBadElements xs = filter (\x -> not $ any ((flip elem) x) (badElements xs) ) xs
badElements
will return a list with all the singleton elements of its parameter (similar to what your badElements
is supposed to do:
badElements [[1],[1,2,3,4],[2],[5,6,7,8]]
[1,2]
removeBadElements
, then, removes all the elements that contain an element of badElements
.
精彩评论