# [erlang-questions] How to "chain" filters?

Robert Virding <>
Mon May 19 22:20:13 CEST 2008

```2008/5/19 Steve Davis <>:

> To give a simple example below -- I wish to perform check2() only on the
> elements that pass check() and I can't see an elegant way to do it!
>
> -module(filter).
> -export([init/0]).
>
> init() ->
>        L = [1,2,3,4,5,6,7,8,9,10],
>        check(L),
>        check2(L, []).

The thing to remember here is that filter, and hence check/1, return the
list of filtered elements. You use this in check2/2. So init/1 should be
written:

init() ->
L0 = [1,2,3,4,5,6,7,8,9,10],
L1 = check(L0),
check2(L1, []).

If you have a sequence of checks you would get:

L1 = check1(L0),
L2 = check2(L1),
L3 = check3(L2),
...

This could be written as folding a list of checks over the returned lists:

Checks =
[fun (L) ->check1(L) end,
fun (L) -> check2(L) end,
...],
lists:foldl(fun (C, L) -> C(L) end, InitialList, Checks)

If this is clearer is a matter of taste. It is at least easier to modify
checks list without having to change variable names. :-)

check(L) -> lists:filter(fun(X) -> X rem 2 =:= 0 end, L).
>
> check2([], A) -> A;
> check2([H | T], A) ->
>        C = lists:filter(fun(X) -> (X + H) rem 3 =:= 0 end, T),
>        C1 = [{H, X, H / X} || X <- C],
>        check2(T, lists:append(A, C1)).

You can combine the filter and the list comprehension into one list
comprehension:

C1 = [{H,X,H/X} || X <- T, (X+H) rem 3 =:= 0 ]

In your code you are really using the list comprehension as a map.

A final point: depending on the length of the output list and the
significance of the order of elements it might be better to push the new
elements onto the accumulator list and reverse the result at the end.

Although I realise that this is just example code. :-) Out of interest what
are doing?

Robert

In my actual code I have 5 non-trivial filters and I'm trying at all
> costs to avoid duplication of tests, The example code below exactly
> specifies the issue (without the detail). i.e. for members of the list
> data that pass the initial check (in this case they are even numbers),
> perfom check2... check2 requires that each candidate element should be
> checked against all other members of the list (but not itself) and
> should not duplicate any pairwise test in the "expensive" check2...
> (my data is actually records so avoiding the issue by using the fact
> that value of the list elements in the example is not going to help!)
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080519/37f37546/attachment.html>
```