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.
$\endgroup$
Commented
Jun 9, 2014 at 9:46
Evaluate
Delete[Cos[a], 0]
before seqHHA
sees it, so there is effectively no surrounding expression. What am I missing?
$\endgroup$
Commented
Jun 9, 2014 at 9:51
Attributes[seqHHA] = {SequenceHold}; seqHHA[Delete[Cos[a], 0]]
$\endgroup$
Commented
Jun 9, 2014 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]
.
$\endgroup$
Commented
Jun 9, 2014 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.
$\endgroup$
Head
and FullForm
to them - everything seems to be right.
$\endgroup$
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
.
$\endgroup$
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
$\endgroup$
Commented
Jun 9, 2014 at 3:54
Sequence
will not evaluate inside a head with HoldAllComplete
or SequenceHold
attributes.
$\endgroup$
Commented
Jun 9, 2014 at 9: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.
Cos
by List
.
$\endgroup$
Commented
Sep 6, 2016 at 23:16
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.
$\endgroup$
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]
? $\endgroup$a
has headSymbol
. All you can do is to replace a head with something else or extract parts of an expression. $\endgroup$Sequence
as head. $\endgroup$Identity
$\endgroup$Sequence @@@ List[List[a, b], List[a, c]]
. But you're right, for examples like in your answerIdentity
does the job. $\endgroup$