# Dynamically remove element from list based on test

Suppose I have a list

l = {a, b, c, d, e, f....}


I would like to remove one of each pair {x,y} if some function check[x,y] returns xor y (or do nothing for that particular pair if the function returns {}). The order of the list is important. For example, if

check[c,e] === c;
check[a,f] === f;


and check on any other combination is empty, the final list should be

{a, b, d, e, ...}


I know how to write a for loop and do index-based removal, but is it a slicker way to do it using Mathematica's list manipulation functions?

EDIT: The check function should be non-overlapping in my usage, but in case if there is problematic overlap, say

check[a,e] === a;
check[a,f] === f;


both e and f should remain, since after removal of a (assuming position of a is earlier than f), there is no pair that can be formed with {a,f}.

-
I am presuming Check is intended to be your own, custom function but that name is already in use. User symbols should start with lower case letters. –  Mr.Wizard Oct 6 '12 at 8:37
What happens if check[a,b] == a and check[a,d] == a? Is it sufficient to remove a? Should the second check be performed at all? –  Mr.Wizard Oct 6 '12 at 8:44
@Mr.Wizard: Good catch! Question edited. –  polyglot Oct 6 '12 at 8:53
Now I am wondering why f is removed and not a -- should the element that is not returned be removed? –  Mr.Wizard Oct 6 '12 at 9:05
It depends on definition of check of course; question again edited for consistency. (It proves that I should go to bed instead...) –  polyglot Oct 6 '12 at 9:10

## 2 Answers

You said that your check should be non-overlapping. For that simplified case I believe this works:

ClearAll[check]
check[c, e] = c;
check[a, f] = f;
check[__] = {};

lst = {a, b, c, d, e, f};
DeleteCases[lst,
Alternatives @@ Flatten[check @@@ Subsets[lst, {2}]]
]


{a, b, d, e}

I'm still working on the more complex version.

-

Here's one implementation:

l = {a, b, c, d, e, f};
check[x_, y_] := If[MemberQ[l, x] && MemberQ[l, y], RandomChoice[{x, y}]]
Fold[DeleteCases, l, {check[c, e], check[a, f]}]


{a, b, d, e}

Edit

A version that checks all subset pairs:

l = {a, b, c, d, e, f};
s = Subsets[l, {2}];
check[{x_, y_}] := If[MemberQ[l, x] && MemberQ[l, y], RandomChoice[{x, y}]]
(l = DeleteCases[l, check[#]]) & /@ s;
l


{a}

As ployglot's edit observes, progressively removing check results from l results in less matches than using Fold, i.e.

Fold[DeleteCases, l, check[#] & /@ s]


{ }

-
You seem to have a very different interpretation of the question. Would you take a look at my present answer and tell me if you still think you've got it right? (I don't mean that condescendingly; rather I'm asking because I don't know for sure that I've got it right.) –  Mr.Wizard Oct 6 '12 at 9:36
@ Mr.Wizard - seems to depend how specific polyglot intends his example to be. –  Chris Degnen Oct 6 '12 at 10:03