Получение всех листьев из выражения - PullRequest
6 голосов
/ 19 августа 2011

Я хотел бы получить List (в идеале набор - отбрасывание повторений - но, предполагая, что прямого способа сделать это не будет, я просто использую Union) листьев из данного выражения.

Например, выражение

ArcTan[(-1 + 2*x)/Sqrt[3]]/Sqrt[3]

имеет LeafCount из 18:

  • -1 (3)
  • 2 (3)
  • 3 (2)
  • x
  • ArcTan
  • Plus
  • Мощность (2)
  • Rational (2)
  • Times (3)

, поэтому я хотел бы что-то вроде

{-1, 2, 3, x, ArcTan, Plus, Power, Rational, Times}

На самом деле, я действительно просто хочу, чтобы функции так

{ArcTan, Plus, Power, Rational, Times}

было бы идеально, но, вероятно, есть какой-то не слишком сложный способ отфильтровать их, когда они у меня есть.

Мне повезло с

H[s_] := If[LeafCount[s] == 1, s, Head[s]]
H /@ Level[expr, 1, Heads -> True]
H /@ Level[expr, 2, Heads -> True]
(* ... *)

, но ячувствую, что должен быть лучший способ.

Ответы [ 4 ]

8 голосов
/ 19 августа 2011

Вы можете использовать Cases для этого:

In[176]:= 
Cases[ArcTan[(-1 + 2*x)/Sqrt[3]]/Sqrt[3], h_[___] :> h, 
  {0,Infinity}] // DeleteDuplicates

Out[176]= {Rational, Power, Times, Plus, ArcTan}
7 голосов
/ 19 августа 2011

Ваше собственное решение не кажется плохим:

expr = ArcTan[(-1 + 2*x)/Sqrt[3]]/Sqrt[3];

H[s_] := If[LeafCount[s] == 1, s, Head[s]]

H /@ Level[exp, -1, Heads -> True] // Union
{-1, 2, 3, ArcTan, Plus, Power, Rational, Times, x}

Метод Бретта Чемпиона более упрощен, но я бы немного его изменил:

Union@Cases[expr, h_[___] :> h, {0, -1}]

Таким образом, вы поднимаете голову верхнего уровня, например ArcTan in:

expr = ArcTan[(-1 + 2*x)/Sqrt[3]];
6 голосов
/ 19 августа 2011

Для исходного вопроса можно получить все листья через уровень со спецификацией уровня {-1} и учетом голов.

In[87]:= Level[ArcTan[(-1 + 2*x)/Sqrt[3]]/Sqrt[3], {-1}, Heads -> True]

Out[87]= {Times, Power, 3, -(1/2), ArcTan, Times, Power, 3, -(1/
    2), Plus, -1, Times, 2, x}

Даниэль Лихтблау

4 голосов
/ 19 августа 2011

Вот что я придумала ...

In[92]:= f[e_] := DeleteDuplicates[Prepend[Head[#] & /@ Level[e, Depth[e]], Head[e]]]

In[93]:= f[ArcTan[(-1 + 2*x)/Sqrt[3]]/Sqrt[3]]

Out[93]=  {Times, Integer, Rational, Power, Symbol, Plus, ArcTan}

Вы можете легко удалить Integer и Symbol.


Edit:

Теперь давайте обернем выражение в список, чтобы убедиться, что мы получаем самую верхнюю голову. (Исходное выражение было Times в качестве его головы, но оно также было дважды внутри.

In[139]:= a = {ArcTan[(-1 + 2*x)/Sqrt[3]]/Sqrt[3]}
In[140]:= TreeForm[a, AspectRatio -> .7]

TreeForm

In[142]:= f[a]
Out[142]= {List, Integer, Rational, Power, Symbol, Times, Plus, ArcTan}
...