tags:

views:

166

answers:

4

Suppose there are two lists a = {a1, a2, a3} and b = {b1, b2, b3}, and I want to write an assignment statement to make a1=b1,a2=b2,a3=b3 which only refers to a and b:

Thread[a = b]

But it only makes a={b1,b2,b3}. Using := (SetDelayed) instead of = doesn't work either.
Any solution? Thanks.

+1  A: 

Well, if they are really called a1, a2, etc, you could do this:

Assign[x_, y_] := Module[{s1, s2, n, sn},
  s1 = SymbolName[Unevaluated[x]];
  s2 = SymbolName[Unevaluated[y]];

    For[n = 1, n <= Length[x] && n <= Length[y], n++,
      sn = ToString[n];
      Evaluate[Symbol[s1 <> sn]] = Evaluate[Symbol[s2 <> sn]]
    ]
  ]

SetAttributes[Assign, HoldAll]

And then

Clear[b1, b2, b3];
Clear[a1, a2, a3];

a = {a1, a2, a3}
b = {b1, b2, b3}

Assign[a, b]
a

Gives the results for a, b and a again as:

{a1, a2, a3}
{b1, b2, b3}
{b1, b2, b3}

As expected.

In general you can create expressions like these from proper use of SymbolName and Symbol, but be careful with your evaluation. If I had written SymbolName[x] (without the Unevaluated) then it would've interpreted that as SymbolName[{a1, a2, a3}], which is clearly not desirable. Not using Evaluate on Symbol[s1 <> sn] will have Mathematica complain that you're trying to reassign the Symbol function.

Joren
Yikes. I think I prefer my solution `:)`
Will Robertson
Yes, yours is infinitely better. (Upvoted) I blame the early morning, and months of working in imperative languages without touching Mathematica :)
Joren
Oh, I definitely know that feeling!
Will Robertson
+4  A: 

I think the Thread only works on "explicit" lists; the variables need to be expanded before being operated on.

After some experimentation, this works for me:

a = {a1, a2, a3};
b = {b1, b2, b3};
Thread[Set[Evaluate@a, Evaluate@b]];
{a1, a2, a3}

You could also write Thread[Evaluate@a = Evaluate@b]; just depends whichever you find more readable.

Will Robertson
Thanks.Actually Evaluate@a = Evaluate@b is enough.I didn't know the command 'Evaluate'.
Explogit
+1  A: 

Here's another solution:

a = {a1, a2, a3};
b = {b1, b2, b3};

each[{x_, y_}, Transpose[{a, b}],
  x = y]

Which uses my handy each function:

SetAttributes[each, HoldAll];                (* each[pattern, list, body]     *)
each[pat_, lst_, bod_] :=                    (*  converts pattern to body for *)
  Scan[Replace[#, pat:>bod]&, Evaluate@lst]  (*   each element of list.       *)

Similarly, you can do this:

MapThread[(#1 = #2)&, {a, b}]
dreeves
A: 

What's wrong with

MapThread[Set,{{a1,a2,a3},{b1,b2,b3}}]

?

none