15
$\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$
4
  • $\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
    Commented Sep 28, 2015 at 14:15
  • $\begingroup$ Closely related: mathematica.stackexchange.com/q/2821/12 $\endgroup$
    – Szabolcs
    Commented Sep 29, 2015 at 8:03
  • $\begingroup$ This question is a version of (13414) and (51541). $\endgroup$
    – Mr.Wizard
    Commented Jul 7, 2016 at 21:19
  • $\begingroup$ Applying Map at level {-1} covers both cases. $\endgroup$
    – Alan
    Commented Oct 28, 2022 at 13:40

7 Answers 7

21
$\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$
5
  • $\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
    Commented Sep 29, 2015 at 17:08
  • 2
    $\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$ Commented Sep 29, 2015 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$ Commented Sep 29, 2015 at 17:59
  • $\begingroup$ Is it correct to think of l as a function that defines a pure function? (specifically, it looks like l` uses the input f to define a pure function based on f?) $\endgroup$
    – user106860
    Commented Nov 12, 2020 at 19:04
  • $\begingroup$ @user106860 I think, the simplest way to think of l is that it is similar to a decorator in python. It takes a function and returns a modified function which adds listability (which happens to be implemented using Function, but that's an implementation detail). $\endgroup$ Commented Nov 12, 2020 at 19:55
18
$\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$
1
  • 1
    $\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
    Commented Sep 29, 2015 at 17:12
10
$\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
  • 2
    $\begingroup$ Map[Greater[#, 1] &, {{0.6, 1.2}, {5, 0.1}}, {-1}] $\endgroup$
    – yode
    Commented Jul 7, 2016 at 21:56
9
$\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$
0
7
$\begingroup$

Check Positive.

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

Positive[{0.6, 1.2}-1]
$\endgroup$
3
$\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$
0
$\begingroup$

We can use the RightTriangle operator

v_?VectorQ  \[RightTriangle] n_ := Map[# > n &, v, {1}]
v_?MatrixQ  \[RightTriangle] n_ := Map[# > n &, v, {2}]

{0.6, 1.2} \[RightTriangle] 1

{False, True}

{{0.6, 1.2}, {5, 0.1}} \[RightTriangle] 1

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

Inside Mathematica it displays nicely like

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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