8
$\begingroup$

Suppose you have the list list={a,Sin[b+c],d+c}. What I want is to transform all elements of list with head Plus into a list again, so that the desired output would be {a,Sin[b+c],d,c}. Simply using List@@ or /.Plus->List will for sure not work since it either transforms all heads (including those that should be left unchanged) or e.g. replaces function arguments.

So what is a neat way to accomplish this potentially very easy task?

$\endgroup$
3
  • 1
    $\begingroup$ Does the order matter, i.e., {a, Sin[b+c],c,d} vs your result. $\endgroup$
    – ciao
    Aug 11, 2015 at 2:07
  • $\begingroup$ @ciao The order does not matter. All elements will be symbolic terms that will be summed up at the very end of a long computation. But thanks for pointing this out - I didn't think about the importance while posting the question :) $\endgroup$
    – Lukas
    Aug 11, 2015 at 2:45
  • $\begingroup$ Then Jens' answer is the way to go... $\endgroup$
    – ciao
    Aug 11, 2015 at 2:50

4 Answers 4

8
$\begingroup$

How about this?

list = {a, Sin[b + c], d + c};

Replace[list, HoldPattern[Plus[x__]] :> Sequence[x], 1]

(* ==> {a, Sin[b + c], {c, d}} *)

Here, HoldPattern is needed to prevent the Plus from being swallowed. I use Replace because it allows me to specify the level 1 at which the replacement is to occur.

$\endgroup$
9
  • $\begingroup$ Not what they're after... c d s/b sequence... $\endgroup$
    – ciao
    Aug 11, 2015 at 2:12
  • $\begingroup$ @Ciao Oh, right... $\endgroup$
    – Jens
    Aug 11, 2015 at 2:13
  • $\begingroup$ And if order matters.... whole 'nother ball-o-wax, +1 though ;-) $\endgroup$
    – ciao
    Aug 11, 2015 at 2:14
  • $\begingroup$ @ciao Thanks - you're right that the order could be tricky because you have to deal with the lexical rules. $\endgroup$
    – Jens
    Aug 11, 2015 at 2:16
  • 4
    $\begingroup$ You can also do Replace[list, Plus -> Sequence, {2}, Heads -> True] $\endgroup$
    – mfvonh
    Aug 11, 2015 at 3:01
4
$\begingroup$
list = {a, Sin[b + c], d + c, g + h + i};

Using ReplaceAt (new in 13.1)

ReplaceAt[Plus[a__] :> List @@ a, Position[list, _Plus, 1]] @ list

{a, Sin[b + c], {c, d}, {g, h, i}}

$\endgroup$
4
$\begingroup$
list /. {a_[_Plus] :> a, Plus -> List}
{a, Sin[b + c], {c, d}}
Replace[list, Plus -> List, 2, Heads -> True]
{a, Sin[b + c], {c, d}}
ReplacePart[list, Position[list, Plus, 2] -> List]
{a, Sin[b + c], {c, d}}
MapAt[List &, list, Position[list, Plus, 2]]
{a, Sin[b + c], {c, d}}
list[[## & @@ First[Position[list, Plus, 2]]]] = List; list
{a, Sin[b + c], {c, d}}
$\endgroup$
2
$\begingroup$

Grabbing the @eldo's list and using Cases:

list = {a, Sin[b + c], d + c, g + h + i};

Cases[list, x_ :> If[SameQ[Head[x], Plus], List @@ x, x]]

(*{a, Sin[b + c], {c, d}, {g, h, i}}*)

Or using If and Map:

If[Head[#] === Plus, # /. Plus -> Function[{##}], #] & /@ list

(*{a, Sin[b + c], {c, d}, {g, h, i}}*)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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