GroupBy with several test features

Is there a better and more concise way to write the following code in Haskell? I tried using if..else , but this is becoming less readable than the following. I want to not go over the xs list (which is huge!) 8 times, just to separate the elements from the 8 groups. groupBy from Data.List performs only one function of the test condition: (a -> a -> Bool) -> [a] -> [[a]] .

 x1 = filter (check condition1) xs x2 = filter (check condition2) xs x3 = filter (check condition3) xs x4 = filter (check condition4) xs x5 = filter (check condition5) xs x6 = filter (check condition6) xs x7 = filter (check condition7) xs x8 = filter (check condition8) xs results = [x1,x2,x3,x4,x5,x6,x7,x8] 
+4
source share
7 answers

This moves only one list:

 import Data.Functor import Control.Monad filterN :: [a -> Bool] -> [a] -> [[a]] filterN ps = map catMaybes . transpose . map (\x -> map (\p -> x <$ guard (px)) ps) 

For each element of the list, map lists Maybe s, each Maybe corresponding to one of the predicates; it is Nothing if the element does not satisfy the predicate, or Just x if it satisfies the predicate. Then transpose shuffles all these lists so that the list is organized by the predicate and not the element, and map catMaybes discards entries for elements that do not satisfy the predicate.

Some explanation: x <$ m is fmap (const x) m , and for Maybe , guard b is if b then Just () else Nothing , so x <$ guard b is if b then Just x else Nothing .

map can also be written as map (\x -> [x <$ guard (px) | p <- ps]) .

+5
source

If you insist that one passage be viewed only once, you can write

 filterMulti :: [a -> Bool] -> [a] -> [[a]] filterMulti fs xs = go (reverse xs) (repeat []) where go [] acc = acc go (y:ys) acc = go ys $ zipWith (\fa -> if fy then y:a else a) fs acc 
+4
source
 map (\ cond -> filter (check cond) xs) [condition1, condition2, ..., condition8] 
+3
source

I think you could use groupWith from GHC.Exts .

If you write a -> b function to assign each element in xs its own "class", I believe that groupWith would separate xs way you want, by going through the list only once.

+2
source

groupBy really does not do what you want; even if it accepts several predicate functions, it does not perform filtering in the list. It simply groups continuous sequences of list items that satisfy a certain condition. Even if your filter conditions, when combined, cover all the elements in the attached list, this is still a different operation. For example, groupBy will not reorder list items, nor will it be able to include this item more than once in the result, while your operation can do both of these things.

This function will do what you are looking for:

 import Control.Applicative filterMulti :: [a -> Bool] -> [a] -> [[a]] filterMulti ps as = filter <$> ps <*> pure as 

As an example:

 > filterMulti [(<2), (>=5)] [2, 5, 1, -2, 5, 1, 7, 3, -20, 76, 8] [[1, -2, 1, -20], [5, 5, 7, 76, 8]] 
+1
source

As an addition to nietaki's answer (it should be a comment, but it is too long, so if its answer is correct, accept it!), The function a -> b can be written as a series of nested if ... then .. else , but it not very idiomatic Haskell and not very extensible. This might be a little better:

 import Data.List (elemIndex) import GHC.Exts (groupWith) f xs = groupWith test xs where test x = elemIndex . map ($ x) $ [condition1, ..., condition8] 

It classifies each element by the first condition_ , which satisfies (and puts those that do not satisfy anyone in their own category).

(The documentation for elemIndex here .)

+1
source

The first function will return a list of "uppdated" lists, and the second function will go through the entire list and for each value will update the list

 myfilter :: a -> [a -> Bool] -> [[a]] -> [[a]] myfilter _ [] [] = [] myfilter xf:fs l:ls | fx = (x:l): Myfilter x fs ls | otherwise = l:Myfilter x fs ls filterall :: [a] -> [a -> Bool] -> [[a]] -> [[a]] filterall [] _ l = l filterall x:xs fl l:ls = filterall xs fl (myfilter x fl l) 

This must be called using filterall xs [condition1,condition2...] [[],[]...]

+1
source

Source: https://habr.com/ru/post/1403217/


All Articles