12
$\begingroup$

This question could sound pretty silly but I can't find a way to apply element -wise tests to a list.

For example if I digit

{0.6, 1.2}>1
{{0.6,1.2},{5,0.1}}>1

I would expect to obtain

{False,True}
{{False,True},{True, False}}

respectively, but it is not the case.

Of course I can define a function or using Map, but I can't believe there is not a core function providing this kind of result. Thank you for any indication

$\endgroup$
  • $\begingroup$ Greetings! Make the most of Mma.SE and take the tour now. Help us to help you, write an excellent question. Edit if improvable, show due diligence, give brief context, include minimum working examples of code and data in formatted form. As you receive give back, vote and answer questions, keep the site useful, be kind, correct mistakes and share what you have learned. $\endgroup$ – rhermans Sep 28 '15 at 14:15
  • $\begingroup$ Closely related: mathematica.stackexchange.com/q/2821/12 $\endgroup$ – Szabolcs Sep 29 '15 at 8:03
  • $\begingroup$ This question is a version of (13414) and (51541). $\endgroup$ – Mr.Wizard Jul 7 '16 at 21:19
19
$\begingroup$

To my knowledge, there aren't built-in versions for comparison operators that would be automatically threaded over lists. One reason for that is that Mathematica is a symbolic system, and every auto-simplification has a cost, because there may be cases when this isn't desirable.

It is relatively easy however to construct the behavior you want:

ClearAll[l];
l[f_] := Function[Null, f[##], Listable]

Now, you can call:

{{0.6, 1.2}, {5, 0.1}} ~ l[Greater] ~ 1

(* {{False, True}, {True, False}} *)

and similarly with other comparison operations.

Note that, since you didn't mention efficiency, I intentionally left this aspect out. If you have large numerical lists, there are vastly more efficient ways to perform the comparisons, making use of vectorization and packed arrays.

$\endgroup$
  • $\begingroup$ I don't fully get the sintax (I'm just a beginner) but this function does what I was looking for. Thank you $\endgroup$ – dario Sep 29 '15 at 17:08
  • 1
    $\begingroup$ @dario [1/2] The syntax a ~ f ~ b is called infix notation, and is equivalent to f[a,b], but sometimes looks more natural. Like in this case, where it allows to somewhat make up for the notational convenience of comparison operator symbols. The expression a > b can be equivalently rewritten as Greater[a,b] in Mathematica, and similarly for other operators. So, we could also write a ~ Greater ~ b, which doesn't look bad. Now, from this form, my suggestion is only one step further. The function l I proposed is similar in spirit to Python decorator. It takes another function and ... $\endgroup$ – Leonid Shifrin Sep 29 '15 at 17:56
  • $\begingroup$ @dario [2/2] ... makes it Listable - that is, wraps it in a pure function that has a Listable attribute. Due to the way evaluation sequence works in Mathematica, this leads to threading of the function over lists, before it gets applied to the individual elements. As a result, the construct l[Greater] would automatically work on lists of any dimensionality, compared to a single number - as well as for e.g. comparison of two lists with the same dimensions - like say {1,3,5} ~ l[Greater] ~ {6,4,2}. Thanks for the accept. $\endgroup$ – Leonid Shifrin Sep 29 '15 at 17:59
16
$\begingroup$

The BoolEval` package does exactly this. For example:

BoolEval[{0.6, 1.2} > 1]
(* Out: {0, 1} *)

and

BoolEval[{{0.6, 1.2}, {5, 0.1}} > 1]
(* Out: {{0, 1}, {1, 0}} *)

In order to return True and False instead of 0 and 1, you can append /. {0 -> False, 1 -> True}.

$\endgroup$
  • $\begingroup$ This solution work as well as the one I've chosen as "best answer", and is probably more elegant. I haven't chosen this, though, because it requires additional packages. Thank you anyway. $\endgroup$ – dario Sep 29 '15 at 17:12
7
$\begingroup$

Depth 1

MapAt[Greater[#, 1] &, {0.6, 1.2}, {All}]
{False, True}

OR

Thread[Greater[#, 1]] & @ RandomReal[2, 10]
{True, False, False, True, True, True, False, False, False, True}

Depth 2

MapAt[Greater[#, 1] &, {{0.6, 1.2}, {5, 0.1}}, {All, All}]
{{False, True}, {True, False}}

OR

Thread[Greater[#, 1]] & /@ RandomReal[2, {3, 5}]
{{True, True, False, True, True}, 
 {True, False, False, False, False},
 {False, False, False, False, True}}

Depth n

f=MapAt[Greater[#, 1] &, #, Table[All, (Depth[#] - 1)]] &

f[{{{1.6, 0.2}, {3, 0.1}}, {{0.6, 1.2}, {5, 0.1}}}]
{{{True, False}, {True, False}}, {{False, True}, {True, False}}}
f@RandomReal[2, Range[6]]

Mathematica graphics

OR

RandomReal[2, Range[4]] /. (w_Real -> w > 1)
$\endgroup$
  • 1
    $\begingroup$ Map[Greater[#, 1] &, {{0.6, 1.2}, {5, 0.1}}, {-1}] $\endgroup$ – yode Jul 7 '16 at 21:56
5
$\begingroup$

The first example can be done with

Thread[{0.6, 1.2} > 1]

$\ ${False, True}

For the second example Map has to be used for this approach, but maybe in a different way than you excluded in you question:

Thread /@ Thread[{{0.6, 1.2}, {5, 0.1}} > 1]

$\ ${{False, True}, {True, False}}

$\endgroup$
4
$\begingroup$

Check Positive.

For {0.6, 1.2}>1, you may write:

Positive[{0.6, 1.2}-1]
$\endgroup$
2
$\begingroup$

For the better read,I post this solution as an answer

Map[Greater[#,1]&,{{0.6,1.2},{5,0.1}},{-1}]

{{False, True}, {True, False}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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