# How can I convert a Piecewise into a nested If?

For later conversion into a programming language where if is the only conditional construct, I would like to convert a Piecewise into a nested If in Mathematica. For instance, how can I convert:

f = Piecewise[{{x^3, x < -1}, {-x^2, -1 <= x < 0}, {x, 0 <= x < 1}, {Sqrt[x], 1 <= x}}]


into

If[x < -1, x^3, If[-1 <= x < 0, -x^2, If[0 <= x < 1, x, If[1 <= x, Sqrt[x], 0]]]]


?

Note the structure of Piecewise. The first element is a list of {value, condition} pairs and the second element is the "default" value for when no other condition applies. If you view it as a list, here's how f looks:

f /. Piecewise -> List

{{{x^3, x < -1}, {-x^2, -1 <= x < 0}, {x, 0 <= x < 1}, {Sqrt[x], 1 <= x}}, 0}


First, here is a recursive function to nest each list at the third position of the previous list, stopping at the deepest list.

nestLists[lists_] := If[Length[lists] == 1, lists[[1]], {Sequence @@ lists[[1]], nestLists[Rest[lists]]}]


This lets us do this:

nestLists[Map[Reverse,f[[1]]]


yielding

{x < -1, x^3, {-1 <= x < 0, -x^2, {0 <= x < 1, x, {1 <= x, Sqrt[x]}}}}


We still need to insert the default value into the third position of the deepest list, then convert the Lists to Ifs.

pwti[pw_] := ReplaceAll[Insert[#, pw[[2]], ConstantArray[-1, Length[Flatten[#]]/2]] &[nestLists[Map[Reverse, pw[[1]]]]], List -> If]


Now the Piecewise can be directly converted thus:

pwti[f]

If[x < -1, x^3, If[-1 <= x < 0, -x^2, If[0 <= x < 1, x, If[1 <= x, Sqrt[x], 0]]]]


Note that this will probably be broken if any of the values or conditions contains a list...

• Does anyone know a better way? Commented Mar 6, 2015 at 1:56
ifs = Reverse /@ (f /. Piecewise -> List /. {{x__, v_}, e_} :> {x, Join[{e}, v]});
Hold @@ Quiet@(ifs //. {x___, {a__, b__}, {c__, d__}, e___} :> {x, {a, b, {c, d}}, e} /. List -> If)

(* Hold[If[x < -1, x^3, If[-1 <= x < 0, -x^2, If[0 <= x < 1, x, If[1 <= x, Sqrt[x], 0]]]]]*)

• Try on my f3 case...
– ciao
Commented Mar 6, 2015 at 2:50
• @rasher He's migrating the code, so no lists on the new platform either :)} Commented Mar 6, 2015 at 2:58
• Just joking. Or not :) Commented Mar 6, 2015 at 2:58

My quick-n-dirty (meaning pretty untested on anything but simple cases):

toif = With[{if = If @@@ (Reverse /@ #[[1]]), l = #[[2]]},
Nest[{Insert[#[[1]], if[[Length@#[[2]] + 1]], #[[2]]],
Append[#[[2]], -1]} &, {if[[1]], {-1}}, Length@if - 1] //
Insert[#[[1]], l, #[[2]]] &] &;


Seems a bit more robust than your solution:

f1 = Piecewise[{{x^3, x < -1}, {-x^2, -1 <= x < 0}, {x,
0 <= x < 1}, {Sqrt[x], 1 <= x}}];

f2 = Piecewise[{{x*2, x[1] == 2}, {x*3, x[2] == 3}}];

f3 = Piecewise[{{2, x == {1, 2, 3}}, {{1, 2, 3}, x == {3, 2, 1}}, {x,
True}}];

Column[{toif[f1],pwti[f1]," ",
toif[f2],pwti[f2]," ",
toif[f3],pwti[f3]}]

(*

If[x<-1,x^3,If[-1<=x<0,-x^2,If[0<=x<1,x,If[1<=x,Sqrt[x],0]]]]
If[x<-1,x^3,If[-1<=x<0,-x^2,If[0<=x<1,x,If[1<=x,Sqrt[x],0]]]]

If[x[1]==2,2 x,If[x[2]==3,3 x,0]]
0

If[x=={1,2,3},2,If[x=={3,2,1},{1,2,3},x]]
x

*)


I'll ponder further when lounging later, gut tells me there's an elegant way to do this.

Much prettier:

toif2 = Fold[Insert[#2, #1, {-1}] &, Prepend[If @@@ Reverse /@ #[[1]], #[[2]]]] &;

toif2[f3]

(* If[x == {3, 2, 1}, {1, 2, 3}, If[x == {1, 2, 3}, 2, x]] *)


N.b.: this reorders terms, end result is the same. Completely untested - gotta go eat!

pwToIf = With[{fpw = Reverse@Transpose@InternalFromPiecewise@#},
Fold[If[## & @@ #2, #] &, fpw[[1, 2]], fpw[[2 ;;]]]] &;


Examples:

pw = Piecewise[{{x^3, x < -1}, {-x^2, -1 <= x < 0}, {x, 0 <= x < 1}, {Sqrt[x], 1 <= x}}];
pwToIf@pw
(* If[x < -1, x^3, If[-1 <= x < 0, -x^2, If[0 <= x < 1, x, If[1 <= x, Sqrt[x], 0]]]] *)

pw2 = Piecewise[{{x^3, x < -1}, {-x^2, -1 <= x < 0}, {x,  0 <= x < 1}, {Sqrt[x], 1 <= x}}, 100];
pwToIf@pw2
(* If[x < -1, x^3, If[-1 <= x < 0, -x^2, If[0 <= x < 1, x, If[1 <= x, Sqrt[x], 100]]]]*)

pw3 = Piecewise[{{2, x == {1, 2, 3}}, {{1, 2, 3}, x == {3, 2, 1}}, {x, True}}]; (* rasher's f3*)
pwToIf@pw3
(* If[x == {1, 2, 3}, 2, If[x == {3, 2, 1}, {1, 2, 3}, x]] *)

(Fold[{Sequence @@ (Reverse@#2), #1} &, f[[2]], Reverse@f[[1]]]) /.List -> If
(*If[x < -1, x^3,If[-1 <= x < 0, -x^2, If[0 <= x < 1, x, If[1 <= x, Sqrt[x], 0]]]]*)
`