The question of efficient lookup of terms linear relative expression satisfying a given pattern depends strongly on whether coefficients c[om1,...]
themselves can somehow depend on this expression.
If coefficients a
, b
, c
, etc can themselves depend on F
, then none of the above solutions can be reliable. For example, the expression Sin[F[om1]]
contains exactly one expression matching _F
at the first level, so both approaches of Fraccalo and Alexei Boulbitch will return it.
Select[{Sin[F[om1]]}, Count[#, F[_]] == 1 &]
(*Returns {Sin[F[om1]]}*)
ClearAll[count];
count[expr_] := Count[expr, _F, Infinity];
Select[{Sin[F[om1]]}, count[#] == 1 &]
(*Returns {Sin[F[om1]]}*)
In this, the most general case, the only option I see is to use FreeQ
:
list={a[om1,om2,om3,om4,om5,om6]*F[om1] F[om2] F[om4] F[om5] F[om6],b[om1,om2,om3,om4,om5,om6]*F[om1] F[om2],c[om1,om2,om3,om4,om5,om6]*F[om2],d[om1,om2,om3,om4,om5,om6]};
list2=Join@@ConstantArray[list,10000];
RepeatedTiming[
general=Cases[
list2,
(a_/;(FreeQ[a,_F]))*_F
]
]//First
(*0.298*)
However, if coefficients themselves cannot depend on F
and we just need to figure out how many times F[...]
is repeated, then Fraccalo approach is a good option.
RepeatedTiming[
select = Select[list2, Count[#, F[_]] == 1 &]
] // First
(*0.054*)
But we can improve the result a little bit by exploiting the fact that in this case we are not interested in how many there are F[...]
expressions in the terms, what Count
computes. We only need to know, whether there is exactly one expression of the form or not. For this reason, we can try the following:
RepeatedTiming[
pattern = Cases[list2, Repeated[Except[_F], {1}]*_F]
] // First
(*0.0280*)
general === select === pattern
(*True*)
Note, that Except[_F]*_F
will not work here because Times
is Flat
.