3

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?

atapaka
  • 3,954
  • 13
  • 33

3 Answers3

11

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

  • Note: in Lookup the third parameter specifies the default value; in Replace the third parameter is the levelspec on which to operate.

Recommended reading:

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
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.

Vito Vanin
  • 568
  • 2
  • 8
0

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

corr = (! MemberQ[elList, #] & /@ els) /. {True -> 1.13, False -> 1.0}
N.J.Evans
  • 5,093
  • 19
  • 25