Is there any way to completely remove the head of an expression function?
For example, how would I remove the head Cos from Cos[a] to give only a as an output.
Is there any way to completely remove the head of an expression function?
For example, how would I remove the head Cos from Cos[a] to give only a as an output.
You can actually Delete the head of the expression, which is part 0:
Delete[#, 0] & /@ {Cos[a], Sin[b], Tan[c]}
{a, b, c}
With version 10 operator forms:
Delete[0] /@ {Cos[a], Sin[b], Tan[c]}
{a, b, c}
One case of interest may be held expressions. If our expression is:
expr = HoldComplete[2 + 2];
And the head we wish to remove is Plus, we cannot use these:
Identity @@@ expr
Sequence @@@ expr
expr /. Plus -> Identity
expr /. Plus -> Sequence
Replace[expr, _[x__] :> x, 1]
All produce e.g.:
HoldComplete[Identity[2, 2]] (* or Sequence *)
We can use Delete or FlattenAt:
Delete[expr, {1, 0}]
FlattenAt[expr, 1]
HoldComplete[2, 2] HoldComplete[2, 2]
You could also use a pattern that includes the surrounding expression on the right-hand-side, as demonstrated here, e.g.:
expr /. h_[_[x__]] :> h[x]
HoldComplete[2, 2]
As the documentation for Delete reads:
Deleting the head of a whole expression makes the head be Sequence.
Delete[Cos[a], 0]
Sequence[a]
Since this resolves to a in normal evaluation this should usually not be an issue.
Delete, rather than some post-processing of the kernel, you can evaluate: SetAttributes[seqHHA, {SequenceHold, HoldAll}]; seqHHA@Evaluate@Delete[Cos[a], 0]. So I disagree with your latest edit. The "a whole expression" here is the entire first argument of Delete, rather than any "subexpression" of the expression in the first argument.
– Jacob Akkerboom
Jun 09 '14 at 09:46
Evaluate Delete[Cos[a], 0] before seqHHA sees it, so there is effectively no surrounding expression. What am I missing?
– Mr.Wizard
Jun 09 '14 at 09:51
Delete w.r.t. generating Sequence has puzzled me before.
– Jacob Akkerboom
Jun 09 '14 at 10:02
Attributes[seqHHA] = {SequenceHold}; seqHHA[Delete[Cos[a], 0]]
– Mr.Wizard
Jun 09 '14 at 10:17
HoldAll is irrelevant, but caution may be good. For example, Sequence[symb] may not resolve to symb if symb is intended to be a head, in for example Delete[{Sin},0][Pi]. Also compare this with ReleaseHold, i.e. ReleaseHold[Hold[Sin]][Pi].
– Jacob Akkerboom
Jun 09 '14 at 11:51
Does this come close?
Cos[a] /. Cos[a] -> a
Or
Cos[a] /. _[a] -> a
Or
First@Cos[a]
Or
list = {Sin@a, Cos@b};
First /@ list
{a, b}
_[a] with literally a then always returns a. For example Cos[b] isn't matched. I guess you meant /. _[a___] -> a, so that eg lekker[b, c] /. _[a___] -> a works.
– acl
Jun 09 '14 at 00:25
Head and FullForm to them - everything seems to be right.
– eldo
Jun 09 '14 at 00:33
a then it does not get matched, because the a on the right hand side of /. is not a pattern. eg Cos[b] /. _[a] -> a evaluates to Cos[b], ie, the a is matched literally. You probably meant Cos[b] /. _[a_] -> a or, more generally (allowing for multiple arguments) Cos[b] /. _[a___] -> a.
– acl
Jun 09 '14 at 00:40
Cos[b] /. _@a___ -> a :)
– eldo
Jun 09 '14 at 00:45
You remove a head by replacing it with Identity
Cos[a] /. Cos -> Identity
For doing this over lots of expressions:
list = {ArcTan[x], ArcTan[x], ArcTan[x], Cot[x], Cot[z], Cot[x],
ArcTan[z], ArcTanh[y], ArcTanh[x], Cot[y]};
list[[All, 0]] = Identity
or
Identity @@@ list
etc
Sequence might be useful if your expressions come inside other expressions. For example:
num = 10;
lst = MapThread[
#1@#2 &,
{
RandomChoice[{Cos, Sin, Exp, Tan, Cot, ArcTan, ArcTanh}, num],
RandomChoice[{x, y, z}, num]
}
]
(*
{ArcTan[x], ArcTan[x], ArcTan[x], Cot[x], Cot[z], Cot[x], ArcTan[z],
ArcTanh[y], ArcTanh[x], Cot[y]}
*)
(this is just a long-winded way of producing a list), then
Sequence @@ # & /@ lst
(*
{x, x, x, x, z, x, z, y, x, y}
*)
Roughly, Sequence dissolves and its children get promoted whenever it appears as something other than the topmost head, eg f[Sequence[g]] evaluates to f[g]. Thus,
expr = f @@ lst
Sequence @@ # & /@ expr
(*
f[ArcTan[x], ArcTan[x], ArcTan[x], Cot[x], Cot[z], Cot[x], ArcTan[z],
ArcTanh[y], ArcTanh[x], Cot[y]]
f[x, x, x, x, z, x, z, y, x, y]
*)
Sequence @@ # & /@ lst can be written more compactly as Sequence @@@ lst
– Bob Hanlon
Jun 09 '14 at 03:54
Sequence will not evaluate inside a head with HoldAllComplete or SequenceHold attributes.
– Mr.Wizard
Jun 09 '14 at 09:35
I got same problem and did not find good answer here.
Then I found Mathematica function Level is very usefull for this:
f=Cos[a];
Level[f, 1]
{a}
Second argument in level defines the depth of subexpressions to be extracted.
Level[Cos[a + b], 1]
gives you:
{a + b}
Meanwhile Level[cos[a + b], {-1}] completely opens subexpressions:
{a, b}
You strategy with more complex functions than just Cos[a] could be either to undestand and use proper levelspec parameter, or try to change it iteratively looking for your Head in the output list.
Level can have a third argument, that can be used to put the result in something else other than List. For example, Level[Cos[a + b], {-1}, HoldComplete] or Level[Cos[a + b], {-1}, Sequence].
– Karsten7
Sep 07 '16 at 04:00
Level is very useful for getting a list of arguments. For example Level[Plus[a,b,c],1] which you can now Map, Select or something else without having the Plus remain as a head of the output.
– Johu
Sep 17 '18 at 02:05
One can also use DeleteCases (which also works inside held expressions):
DeleteCases[{Sin[Cos[x]], Cos[x], Hold[2 + 2], HoldComplete[2*3]},
Cos | Plus | Times, -1, Heads -> True]
(*{Sin[x], x, Hold[2, 2], HoldComplete[2, 3]}*)
First@Cos[a]? – C. E. Jun 09 '14 at 00:03ahas headSymbol. All you can do is to replace a head with something else or extract parts of an expression. – Oleksandr R. Jun 09 '14 at 00:50Sequenceas head. – acl Jun 09 '14 at 02:36Identity– Mike Honeychurch Jun 09 '14 at 04:18Sequence @@@ List[List[a, b], List[a, c]]. But you're right, for examples like in your answerIdentitydoes the job. – acl Jun 09 '14 at 12:04