Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Suppose that I want to write a function fun that takes an Integer num as input, and returns Red if num == 1, Orange if num == 2, and Yellow if num == 3. One way, I think, to do this is to use Which:

fun[num_Integer] := Which[num == 1, Red, num == 2, Orange, num == 3, Yellow]

Is there a more concise way to write fun? In other words, is there any built-in function (analogous to Which) that I can use that would allow me to avoid typing "num" all the time instead of always having to specify it to Which. Writing fun as a series of nested If statements would be even lengthier.

Do you have any suggestions? Thanks for your time.

share
1  
I usually use Switch as per @jVincent below –  Mike Honeychurch Jan 14 '13 at 23:00
    
Every single one of the methods I thought of are already in the four answers below. That doesn't happen often. Nice coverage guys! –  Mr.Wizard Jan 15 '13 at 2:46

4 Answers 4

up vote 25 down vote accepted

Not really a concise syntax, but you can also do this using Switch, which removes the need for writting the checking, and also allows patterns:

fun[num_Integer] :=
  Switch[num,
  1, "Red",
  2, "Orange",
  3, "Yellow",
  _?PrimeQ, "Purple",
  _, "LightGray"]

I used strings just to make the output nicer to verify the behavior. Naturally you would switch these to the actual colors.

Style[#, fun@#] & /@ Range@20

Numbers colored using the function

share

For example you may do something like

f[i_] := {Red,Orange,Yellow}[[i]]

Edit

You can easily add some robustness:

f[l_List, i_Integer ] := l[[i]] /; 1 <= i <= Length@l;

ll = {Red, Orange, Blue};
f[ll, 3]
share

You could use ReplaceAll to write your function this way:

fun[num_Integer] := num /. {1 -> Red, 2 -> Orange, 3 -> Yellow}

This also allows pattern matching, and works better than switch in case you want to name parts of your pattern:

findpeople[dbconn_, name_] := DBSelect[dbconn, "People", name] /. {
   $Failed :> (Message[findpeople::conn]; $Failed),
   {} :> (Message[findpeople::empty]; $Failed),
       results_List :> results,
       other_ :> (Message[findpeople::err, other]; $Failed)
}
share
1  
Big +1. Not enough love for this answer, folks! The possibility to transparently incorporate error-handling is very valuable. I use similar constructs a lot too. –  Leonid Shifrin Jan 15 '13 at 10:03
2  
+1, you might want to use Replace instead of ReplaceAll for slightly more robustness when replacing unexpected expressions... –  Albert Retey Jan 15 '13 at 11:19

One simple solution is:

fun[1] = Red;
fun[2] = Orange;
fun[3] = Yellow;

A more complex solution that accepts arbitrary equivalence lists at run time:

fun[{ins_, outs_}] :=  Function[x, Piecewise[MapThread[{#2, x == #1} &, {ins, outs}], x]];

f = fun[{{1, 2, 3}, {Red, Orange, Yellow}}];

f[2]

RGBColor[1, 0.5, 0]

share
4  
I think it is a little more efficient to use fun[1]=Red,etc. Using := means that the token Red will evaluated on every call to fun, rather than once. –  m_goldberg Jan 15 '13 at 0:15
    
@m_goldberg, I don't think it makes any difference. –  Rojo Jan 15 '13 at 1:49
    
If you do f[_]=x; x=2;, then f[9] will have to reevaluate x regardless of having used an immediate assignment. If MMA is smart enough to not check when the assignment is to an atom, them it probably is also smart enough with a delayed assignment. But I'm not certain –  Rojo Jan 15 '13 at 1:51
1  
Ok, Forget what I said, I forgot that Red and friends actually evaluate to RGBColor –  Rojo Jan 15 '13 at 1:56
2  
One sleeps, magic happens. –  image_doctor Jan 15 '13 at 8:28

This site is currently not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .