3
$\begingroup$

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?

$\endgroup$
11
$\begingroup$

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:

$\endgroup$
1
$\begingroup$

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.

$\endgroup$
0
$\begingroup$

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

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.