# Replace For with If in Mathematica way

I have this code:

elList = {"H", "C", "N", "O", "F", "Cl"};
els = {"Ca", "O", "C", "Si", "H"};
corr = ConstantArray[1.0, Length@els];
For[i = 1, i <= Length@els, i++,
If[!MemberQ[elList, els[[i]]], corr[[i]] = 1.13];
]


What would be the best way to replace the loop, in other words, how to replace it in the Mathematica way?

My only idea was:

(MemberQ[elList, #] & /@ els) /. {True -> 1.0, False -> 1.13}


Is there a better way or other way?

You can rewrite your idea using If as follows:

If[MemberQ[elList, #], 1., 1.13] & /@ els

{1.13, 1., 1., 1.13, 1.}


However you may find on larger problems that repetitive use of MemberQ is not as fast as you would like, so consider a hash table in the form of an Association, or if using an older version of Mathematica a Dispatch table.

Create a list of Rule expressions using Thread:

rules = Thread[elList -> 1.0]

{"H" -> 1., "C" -> 1., "N" -> 1., "O" -> 1., "F" -> 1., "Cl" -> 1.}


Convert into optimized forms with Association or Dispatch

asc = Association[rules];

disp = Append[rules, _ -> 1.13] // Dispatch;


Apply the hash tables:

Lookup[asc, els, 1.13]

Replace[els, disp, {1}]

{1.13, 1., 1., 1.13, 1.}

{1.13, 1., 1., 1.13, 1.}


If speed is not you concern, may be this can be worth a try

common = Intersection[elList, els];
u = Map[ Position[els, # ] &, common ] ;
corr[[ Flatten[u] ]] = 1.13


This can be fit in a single line, and is almost readable

corr[[ Flatten[ Position[els, # ] & /@ Intersection[elList, els] ] ]] = 1.13


and will seem even more nice if you use (elList esc inter esc els) in place of Intersection[elList,els] - the parentheses around the intersection are required, the precedence of Intersection in operator form seems to be low.

Here's a little one-liner without If, probably not fast on large lists:

corr = (! MemberQ[elList, #] & /@ els) /. {True -> 1.13, False -> 1.0}