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$
  • $\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 Aug 18 '15 at 17:44
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"]]]
| improve this answer | |
$\endgroup$
  • 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 Aug 18 '15 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$ – Patrick Stevens Aug 19 '15 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.

| improve this answer | |
$\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 ;

| improve this answer | |
$\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}]
| improve this answer | |
$\endgroup$
  • 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$ – Dr. belisarius Aug 19 '15 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 Aug 19 '15 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]] (* < , *)

| improve this answer | |
$\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.