10

I have an If statement I need to carry out where the result should be a single number for each time the if is executed. What I have at the moment returns a list for each time the If is executed. I specifically do not want to use a Do loop so is there a way to use Map to do this?

x = {0.897409001634915`, 0.897409001634915`, 0.897409001634915`, 
   0.897409001634915`, 0.897409001634915`, 0.897409001634915`, 
   0.897409001634915`, 0.897409001634915`, 0.897409001634915`, 
   0.897409001634915`, 0.897409001634915`, 0.897409001634915`, 
   0.897409001634915`, 0.897409001634915`, 0.897409001634915`, 
   0.897409001634915`, 0.897409001634915`, 0.897409001634915`, 
   0.897409001634915`, 0.897409001634915`};
y = {0.897409001634915`, 0.897409001634915`, 0.897409001634915`, 
   0.897409001634915`, 0.897409001634915`, 0.897409001634915`, 
   0.897409001634915`, 0.897409001634915`, 0.897409001634915`, 
   0.897409001634915`, 0.897409001634915`, 0.897409001634915`, 
   0.897409001634915`, 0.897409001634915`, 0.897409001634915`, 
   0.897409001634915`, 0.897409001634915`, 0.897409001634915`, 
   0.897409001634915`, 0.897409001634915`};
z = {0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

TimeModelSelection[41]
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

The first few lines of the result are

Map[If[# == 0, x*y, z] &, TimeModelSelection[41], {1}]
{{0.8053429162, 0.8053429162, 0.8053429162, 0.8053429162, 
  0.8053429162, 0.8053429162, 0.8053429162, 0.8053429162, 
  0.8053429162, 0.8053429162, 0.8053429162, 0.8053429162, 
  0.8053429162, 0.8053429162, 0.8053429162, 0.8053429162, 
  0.8053429162, 0.8053429162, 0.8053429162, 
  0.8053429162}, {0.8053429162, 0.8053429162, 0.8053429162, 
  0.8053429162, 0.8053429162, 0.8053429162, 0.8053429162, 
  0.8053429162, 0.8053429162, 0.8053429162, 0.8053429162, 
  0.8053429162, 0.8053429162, 0.8053429162, 0.8053429162, 
  0.8053429162, 0.8053429162, 0.8053429162, 0.8053429162, 
  0.8053429162},...

I have also tried thefollowing without luck

Map[If[# == 0, x[[#]]*y[[#]], z[[#]]] &, TimeModelSelection[41], {1}]
lara
  • 1,028
  • 7
  • 17

2 Answers2

10

If I understand the statement, you wish to do this:

Table[If[time[[i]] == 0, x[[i]] y[[i]], z[[i]]], {i, 1, Length[time]}]

but you wish to do it without Table or Do. One way to accomplish this is quite straightforward:

(1 - time) x y + time z

which gives the same result as above, though this assumes that the time variable is either zero (when you wish to have x*y) or one (when you wish to use z). This uses time as shorthand for your variable TimeModelSelection[41].

Another, more "functional programming" way to approach this is to define the basic operation as a function:

f[{t_, x_, y_, z_}] := If[t == 0, x y, z]

and then call the function using Map

Map[f, # &, {1}] /@ Transpose[{time, x, y, z}]

which again gives the same answer. Finally, for the purists, you can do the same thing without defining any auxiliary function (like f) by using pure functions

Apply[If, {#[[1]] == 0, #[[2]] #[[3]], #[[4]]} &, {1}] /@ Transpose[{time, x, y, z}]

though it is probably hard to read. Mr. Wizard's use of MapThread is probably a better and more readable way to get a purely functional form than this use of Apply.

bill s
  • 68,936
  • 4
  • 101
  • 191
6

bill already showed how to do this very efficiently with a numeric approach, but a bit closer to what you attempted and your direct request is MapThread:

SeedRandom[1]
time = RandomInteger[1, 20]

MapThread[If[# == 0, #2*#3, #4] &, {time, x, y, z}]
{0, 0, 0.805343, 0, 0.805343, 0.805343, 0.805343, 0, 0.805343, 1, 0.805343, 0.805343,
 0.805343, 0.805343, 0.805343, 0.805343, 0.805343, 0, 0, 0}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371