List indexing in mathematica
Let S
be a vector with unique elements, and s
a subset of it, also with unique elements; e.g., S={1,2,3,4,5,6}
and s={1,3,4,6}
. Now given another vector c={7,8,9,7}
, how can I create a vector C=[7,0,8,9,0,7]
, i.e., if S[[i]]
is an element in s
, then C[[i]]
is equal to the element in c
with the same index as S[[i]]
in s
, else zero.
What I have right now looks like
C=Array[0&,Length[S]];
j=1;
For[i=1,i<=Length[S],i++,If[MemberQ[s,S[[i]]],C[[i]]=c[[j]];j=j+1;]];
This works, but coming from a MATLAB background, I hate for
loops and the above operation is a trivial indexing operation in matlab. I'm sure there is a smarter way to accomplish this, a la m开发者_开发问答athematica style. Does anyone have suggestions?
You are replacing elements of S with either an element in c or with 0, so:
ss = {1, 2, 3, 4, 5, 6}
s = {1, 3, 4, 6}
c = {7, 8, 9, 7}
r = Append[MapThread[Rule, {s, c}], Rule[_, 0]]
answer = Map[Replace[#, r] &, ss]
This is faster than what has been posted so far:
ss = {1, 2, 3, 4, 5, 6}; s = {1, 3, 4, 6}; c = {7, 8, 9, 7};
Replace[ss, Dispatch@Append[Thread[s -> c], _ -> 0], 1]
ss = {1, 2, 3, 4, 5, 6};
s = {1, 3, 4, 6};
c = {7, 8, 9, 7};
ss /. Join[MapThread[Rule, {s, c}],Thread[Rule[Complement[ss, s], 0]]]
EDIT or:
answer = 0 ss; answer[[Position[ss, #, 1] & /@ s // Flatten]] = c;
Here's one way. There are probably many others.
s = {1, 2, 3, 4, 5, 6};
subS = {1, 3, 4, 6};
c = {7, 8, 9, 7};
d= s /. {x_Integer :> If[MemberQ[subS, x], c[[Position[subS, x][[1, 1]]]], 0]}
I used lower case variable names throughout as is customary for user-defined symbols.
Mathematica uses curly braces are used for vectors, lists, matrices, and tables.
If S
is always of the form {1, 2, ..., n}
, (e.g., Range[n]
) then this solution using SparseArray
is about twice as fast as @Mr. Wizard's answer in my testing for very large lists:
Normal[SparseArray[Thread[s -> c], n, 0]]
精彩评论