# Is there a concise form of Which or similar conditional?

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.

-
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
We probably need to add PiecewiseColor. – Daniel Lichtblau Jul 15 '15 at 22:19

## 4 Answers

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


-

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]
(* RGBColor[0, 0, 1] *)

-
If you want periodicity: l[[Mod[i, Length[l], 1]]]. – J. M. Jul 16 '15 at 0:35

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)
}

-
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
+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]

-
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. – Rojolalalalalalalalalalalalala 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 – Rojolalalalalalalalalalalalala Jan 15 '13 at 1:51
Ok, Forget what I said, I forgot that Red and friends actually evaluate to RGBColor – Rojolalalalalalalalalalalalala Jan 15 '13 at 1:56
One sleeps, magic happens. – image_doctor Jan 15 '13 at 8:28