Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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
2  
Map[List, {a + b == c + d}, {2}] –  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} –  TomD Jul 12 '13 at 23:47
add comment

2 Answers

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
add comment

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

Clear[unthread];
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 *)

Examples

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
add comment

Your Answer

 
discard

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.