Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

For example

{a + b} == {c + d} // Thread
(*{a + b == c + d}*)

how to get {a + b} == {c + d} from {a + b == c + d} ?

This is my try

Equal @@ List /@ Join @@ {a + b == c + d}

Are there other ways to do this?

share|improve this question
Map[List, {a + b == c + d}, {2}] – Dr. belisarius Jul 12 '13 at 17:15
{a + b == c + d} /. f_[x_, y_] :> f[{x}, {y}] (only in special cases) – Kuba Jul 12 '13 at 17:16
Just for fun: Equal @@ Tuples@{a + b == c + d} => {a + b} == {c + d} – user 106 Jul 12 '13 at 23:47
up vote 6 down vote accepted

One way would be

Distribute[{a + b == c + d}, Equal]

Same as

Thread[{a + b == c + d}, Equal]

More universal

{a + b == c + d}/. f_[g_[x_, y_]] -> g[f[x], f[y]]
share|improve this answer
Thanks, I'm completely a mess on these. How do you change {a==b,c==d} to {a+c==b+d} again using Thread? – xslittlegrass Jul 12 '13 at 20:08
@xslittlegrass, If you really need Thread for this, maybe: {Thread[Total@{a == b, c == d}, Equal]}, another way would be: Inner[Plus, Sequence @@ {a == b, c == d}, Equal] – panda-34 Jul 12 '13 at 20:48
(+1) I like the Thread way. It seems more natural in this case, where threading is basically transposition with different heads. In fact, it seems more universal than the replacement rule, certainly with respect to number of arguments, but also considering that one specifies the head for Thread in the first place, either List by default or explicitly by it optional second argument. – Michael E2 Jul 12 '13 at 21:17

The Thread operation is not completely invertible in all cases, but if we assume that

  • only level 1 is to be considered, and
  • in the original Thread, all arguments had the same head and length,

then the expression can be unthreaded. Perhaps others can extend this.

Here, in unthread[expr, h], if expr is of the form

f[h[a1, a2,...], h[b1, b2,...],...]

the the result will be

h[f[a1, b1,...], f[a1, b2,...],...]

The default for h is List. Thus unthread[f[h[a1, a2,...],..., h] undoes Thread[h[f[a1, b1,...],...], f].

unthread::usage = "unthread[f[args], h]  \"unthreads\"  f  over  args  each with head  h";
unthread::tdlen = "Objects of unequal length in `` cannot be uncombined. :)";
unthread::head = "Objects in `` not all of type ``.";
unthread[expr_, h_: List] /;
     (Length@DeleteDuplicates[Length /@ expr] == 1 ||
       (Message[unthread::tdlen, expr]; False)) &&
     (DeleteDuplicates[Head /@ List @@ expr] == {h} ||
       (Message[unthread::head, expr, h]; False)) := 
  With[{h2 = Head[expr]}, h @@ h2 @@@ Transpose[List @@ List @@@ expr]];
unthread[expr_, h_] := expr;  (* return expressions that do not satisfy criteria *)


unthread[{a + b == c + d}, Equal]
(* {a + b} == {c + d} *)

unthread[g[f[a, aa], f[b, bb], f[c, cc]], f]
(* f[g[a, b, c], g[aa, bb, cc]] *)

unthread[g[f[a, aa], f[b, bb], f[c, cc, ccc]], f]
(* unthread::tdlen: Objects of unequal length in g[f[a,aa], f[b,bb], f[c,cc,ccc]]
    cannot be uncombined. :) *)
(* g[f[a, aa], f[b, bb], f[c, cc, ccc]] *)

unthread[g[f[a, aa], f[b, bb], h[c, cc]], f]
(* unthread::head: Objects in g[f[a,aa], f[b,bb], h[c,cc]] not all of type f. *)
(* g[f[a, aa], f[b, bb], h[c, cc]] *)

An example in which two different Thread operations yield the same output, which shows Thread is not completely reversible.

Thread[f[g[a, b, c], g[aa, bb, cc], d], g]
(* g[f[a, aa, d], f[b, bb, d], f[c, cc, d]] *)

Thread[f[g[a, b, c], g[aa, bb, cc], g[d, d, d]], g]
(* g[f[a, aa, d], f[b, bb, d], f[c, cc, d]] *)
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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