5
$\begingroup$

I have the following list :

list={a^2, b^2, a^-1, a^2+b^2, (a+b+c)^-1, (a+b-c)^-2}
Do[Print[list[[i]]//FullForm],{i,1,Length[list]}]

I want to break this list into two lists: one containing elements starting with Power and another starting with Plus. In this case it will be

list1 = {a^2, b^2, a^-1, (a+b+c)^-1, (a+b-c)^-2}
list2 = {a^2+b^2}

A priori the position of elements starting with Power or Plus is not fixed and also the elements could be complicated. Is it possible to do this?

$\endgroup$
1
  • 2
    $\begingroup$ Try: Cases[list, HoldPattern[Power[]]] and Cases[list, HoldPattern[Plus[]]] $\endgroup$ – Daniel Huber Jan 13 at 13:50
2
$\begingroup$
grouped = GroupBy[list, Head]
<|Power -> {a^2, b^2, 1/a, 1/(a + b + c), 1/(a + b - c)^2}, 
 Plus -> {a^2 + b^2}|>
grouped  /@ {Power, Plus}
{{a^2, b^2, 1/a, 1/(a + b + c), 1/(a + b - c)^2}, 
 {a^2 + b^2}}
Lookup[{Plus, Power}] @ grouped 
{{a^2 + b^2}, 
 {a^2, b^2, 1/a, 1/(a + b + c), 1/(a + b - c)^2}}
KeyTake[Plus] @ grouped 
<|Plus -> {a^2 + b^2}|>
KeyDrop[Plus] @ grouped 
<|Power -> {a^2, b^2, 1/a, 1/(a + b + c), 1/(a + b - c)^2}|>
$\endgroup$
6
$\begingroup$
list = {a^2, b^2, a^-1, a^2+b^2, (a+b+c)^-1, (a+b-c)^-2};

{list1, list2} = GatherBy[list, Head]

(* Out:

{
 {a^2, b^2, a^(-1), (a + b + c)^(-1), (a + b - c)^(-2)}, 
 {a^2 + b^2}
}

*)

If you want to specify in which order the heads should be extracted, then you could use multiple Cases statements:

{powerList, plusList} = Cases[list, Blank[#]]& /@ {Power, Plus}

(* Out: 
{
 {a^2, b^2, 1/a, 1/(a + b + c), 1/(a + b - c)^2},
 {a^2 + b^2}}
}
*)
$\endgroup$
4
  • $\begingroup$ Nice solution, except you don't know in advance which head will be the first in the pair $\endgroup$ – Roma Lee Jan 13 at 19:20
  • $\begingroup$ @RomaLee Good point, although I am not sure that it matters to OP, but it can be easily and automatically addressed. See edit. $\endgroup$ – MarcoB Jan 13 at 19:26
  • $\begingroup$ I always suffer from the absence of TakeDrop analog of Cases/DeleteCases and the necessity to call Cases twice. But because of arbitrary order in Gather, it is almost unavoidable. Another way is to add dummy element with head Plus to the beginning, but then you have to delete it. Not nice either. $\endgroup$ – Roma Lee Jan 13 at 19:31
  • 2
    $\begingroup$ @RomaLee That's why GroupBy is almost always preferable to GatherBy. $\endgroup$ – Sjoerd Smit Jan 14 at 14:39
3
$\begingroup$
{l1, l2} = Function[x, Select[#, #[[0]] === x &]]&[list]/@{Power, Plus}

Alternatively, using Pick:

{lone,ltwo} = Pick[#1, #1[[All,0]], #2]&[list,#]&/@{Power, Plus}

 

l1
l2

$$ \left\{a^2,b^2,\frac{1}{a},\frac{1}{a+b+c},\frac{1}{(a+b-c)^2}\right\} $$

$$ \left\{a^2+b^2\right\} $$

$\endgroup$
2
$\begingroup$

Cases do the job.

{a^2, b^2, a^-1, a^2 + b^2, (a + b + c)^-1, (a + b - c)^-2} // {Cases[_Power]@#, Cases[_Plus]@#} &
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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