0
$\begingroup$

Coming from other functional programming environments (e.g., Clojure) I've become accustomed to some functions that I haven't found equivalents for in Mathematica yet.

The two I reached for last night were every and some.

Every would return True if the provided predicate function is True for every element in the list. (and False otherwise)

Some would return True if the provided predicate function is True for at least one of the elements in the list. (and False otherwise)

Every[{2, 4, 6}, EvenQ] (* would return True *) Every[{2, 4, 5}, EvenQ] (* would return False *) Some[{2, 4, 6}, OddQ] (* would return False *) Some[{2, 4, 5}, OddQ] (* would return True *) 

Perhaps some version of these are built-in and I've failed to find them in the docs?

Or, can we get a once-and-for-all efficient and elegant implementation of these that we can all use?

Or, is such an implementation impossible? (I hope not :)

Kind thanks, as ever.


Apologies if this question has been asked before, I saw some similar things, but none of the existing questions satisfied me.

For example, the following three questions are related, but suffer variously from bad specification in the question and low quality answers:

$\endgroup$
3
  • 3
    $\begingroup$ The answers to the questions you cited don't particularly strike me as being low quality. $\endgroup$ Commented Oct 18, 2013 at 22:45
  • $\begingroup$ You're right, I should have left that subjective judgement out. $\endgroup$ Commented Oct 18, 2013 at 22:54
  • $\begingroup$ Are Or and And are not suitable? $\endgroup$ Commented Oct 19, 2013 at 21:24

2 Answers 2

7
$\begingroup$

Haven't looked into efficiency, but both types of behavior are easily implimented through a run of the mill Map:

every[list_, test_] := And @@ (test /@ list) some[list_, test_] := Or @@ (test /@ list) 

used as:

every[Range[10], EvenQ] (* False *) some[Range[10], EvenQ] (* True *) 

I suspect that the linked solution (https://stackoverflow.com/a/8512766/2142251) is close to the optimal you'll get, as it uses Select which short circuits on the test. From that method you would define them as:

every[list_, cond_] := Select[list, ! cond@# &, 1] === {}; some[list_, cond_] := Select[list, cond@# &, 1] =!= {}; 

Update:

So after doing some quick benchmarking of the two, I have no definitive conclusion on which method is better. The short circuit naturally outperforms when the check fails quickly but for full list checks map wins out. So Let's assume that a function like every will be used in situations where you'd reasonably expect everything to check half the time, then you're in a situation where the map is quicker for every, but select is quicker for some. All this is however just based on some quick and dirty timings, so anyone feel free to build upon my thoughts or tear them apart.

$\endgroup$
1
  • $\begingroup$ Wow, so fast. Easy upvote, this is what I was trying to do, but I hadn't understood Prefix/@ or the third argument to Select before. I learned a lot, warm thanks. $\endgroup$ Commented Oct 18, 2013 at 22:28
4
$\begingroup$

Pattern-based solution

every[list_, test_] := MatchQ[list, _[__?test]] some[list_, test_] := MemberQ[list, _?test] 

It is also from SO (especially Mr.Wizard's answer).

My tests show that it is as fast as the approach with Select (may be a bit faster).

$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.