Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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}.

share|improve this question
    
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
1  
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 2

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] 

{ }

share|improve this answer
    
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

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.