3
$\begingroup$

I've written the following function (the code includes the output):

f1[L_, n_] := 
For[i = 1, i < Length[L], i++, 
If[L[[i]][[1]] > n Or L[[i]][[2]] > n, Print["Bad"], Print["Good"]]]
f1[{{0, 1}, {2, 3}, {4, 5}, {6, 7}}, 5]
Good
Good
Good

Instead of outputting "Good" thrice and "Bad" once.

Could someone please tell me where I went wrong? I'm stumped. Any help would be greatly appreciated.

$\endgroup$
1
  • $\begingroup$ Welcome to Mathematica.SE! I hope you will become a regular contributor. To get started, 1) take the introductory Tour now, 2) when you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge, 3) remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign, and 4) give help too, by answering questions in your areas of expertise. $\endgroup$
    – bbgodfrey
    Commented Aug 18, 2015 at 17:44

5 Answers 5

5
$\begingroup$

Probably better:

f[l_, n_] := Or @@@ Thread /@ Thread[l > n] /. {True -> "Bad", False -> "Good"}

l = {{0, 1}, {2, 3}, {4, 5}, {6, 7}};
f[l, 5]
(* {"Good", "Good", "Good", "Bad"} *)

Looping is strongly discouraged in Mathematica, but if you still want to stick with it:

f1[l_, n_] := For[i = 1, i <= Length[l], i++, 
                 If[Or[l[[i, 1]] > n , l[[i, 2]] > n], Print["Bad"], Print["Good"]]]
$\endgroup$
2
  • 1
    $\begingroup$ OK, I figured it out now. For some reason, using "Or" instead of "| |" was causing the problem. Thanks for the answers everyone. Also, I was off by one when I specified when the function should terminate. $\endgroup$
    – gndz
    Commented Aug 18, 2015 at 17:36
  • $\begingroup$ "For some reason": for the same reason as Sin[x] Integrate {x, 0, 1} won't return 1-Cos[1]. $\endgroup$ Commented Aug 19, 2015 at 7:01
6
$\begingroup$

You told Mathematica to terminate at i == Length[L]-1, not at Length[L]. Additionally, your use of Or is almost certainly not what you intended. I advise reading the Mathematica documentation under tutorial/EverythingIsAnExpression.

$\endgroup$
6
$\begingroup$

Another alternative using Map and a pure function & which are common Mathematica idioms:

f1[el_, n_] := (#[[1]] > n || #[[2]] > n) & /@ el /. {True -> "Bad", False -> "Good"}

The use of capital letters for variables, functions etc is discouraged as they may clash with built in definitions.

Print is also not much used, Mathematica will automatically display the return value from the function unless you tell it not to using a terminating ;

$\endgroup$
3
$\begingroup$

I strongly advocate the use of a functional idiom such as Map or Thread as shown in the answers by Belisarius and image_doctor.

But it is worth noting that you can get something close to your original syntax using Infix notation (see this guide for more information. Aside from the issue with your termination condition, you were trying to use Or as an infix operator (like + is for Plus), instead of the correct infix form of ||. You could if you really wanted to use Or as the infix operator by nesting it in the ~ infix symbols. But watch out! Or has higher precedence than equality/inequality, so you then have to wrap your conditions in parentheses. (See this guide on precedence.) The final expression would look like this:

f1[L_, n_] := 
 For[i = 1, i <= Length[L], i++, 
  If[(L[[i]][[1]] > n) ~ Or ~ (L[[i]][[2]] > n), 
  Print["Bad"], Print["Good"]] ] 

Please be aware that I do not advocate this particular syntax, but am only showing it for educational purposes.

Personally, I'd suggest

 Max[#] > 5 & /@ {{0, 1}, {2, 3}, {4, 5}, {6, 7}}

Or use the explicit form of Map (/@) to get at the individual matrix elements at level 2 of the list, and then Apply Or to each row using the short-form notation @@@.

Or @@@ Map[# > 5 &, {{0, 1}, {2, 3}, {4, 5}, {6, 7}}, {2}]
$\endgroup$
2
  • 1
    $\begingroup$ Please be aware that I do not advocate this particular syntax, but am only showing it for educational purposes +1. Coming soon to theaters "The wars of the mods" :D $\endgroup$ Commented Aug 19, 2015 at 16:27
  • 1
    $\begingroup$ Haha @Belisarius - I have nothing against infix in general, but you have to admit that ~ Or ~ is ungainly relative to ||. $\endgroup$
    – Verbeia
    Commented Aug 19, 2015 at 22:59
1
$\begingroup$
f1[L_, n_] := 
 For[i = 1, i <= Length[L], i++, 
  If[Or[L[[i, 1]] > n , L[[i, 2]] > n], Print["Bad ", L[[i]]], 
   Print["Good ", L[[i]]]]]

You need to note the difference between:

For[i = 1, i <= 10, i++; Print[i]] (* <= ;*)

For[i = 1, i <= 10, i++, Print[i]] (* <= ,*)

For[i = 1, i < 10, i++; Print[i]] (* < ; *)

For[i = 1, i < 10, i++, Print[i]] (* < , *)

$\endgroup$
0

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.