While working on my answer to this question, it occurred to me that it is difficult to match a finite range of elements. With the built in patterns, you can match 1 element (_
), 1 or more elements (__
), or zero or more elements (___
). To match more than one element, I used PatternSequence
, like this
a:PatternSequence[_,_,_]
or, more generically
a:PatternSequence@@Array[_&,3].
(Using a Condition
would have also worked.) To match a range of n to m elements we could do
a:Alternatives@@( PatternSequence @@@ Array[_&, {n,m}] ),
but that is a rather convoluted way to accomplish something that can be done by
a__ /; n <= Length[{a}] <= m.
However, this brings up an interesting question, using the Condition
form it is straightforward to match the range 0 to n,
a___ /; Length[{a}] <= n,
but can this be done using patterns alone, i.e. without using Condition
(/;
)? More specifically, how would one go about matching 0 elements without adding a condition? Also, which is faster?
Maybe you could do something with Repeated
. E.g.
Cases[{{1, 2, 3}, {1}, {1, 2, 3, 4, 5}, {1,2}}, {Repeated[_, {2, 4}]}]
gives the same result as
Cases[{{1, 2, 3}, {1}, {1, 2, 3, 4, 5}, {1,2}}, {a___ /; 2 <= Length[{a}] <= 4}]
The first method seems faster than the second. For example
tab = Table[Range[RandomInteger[1000]], {1000}];
Timing[t1 = Cases[tab, {a___ /; 0 <= Length[{a}] <= 100}];]
Timing[t2 = Cases[tab, {Repeated[_, {0, 100}]}];]
SameQ[t1, t2]
returns on my system
{0.027801, Null}
{0.000733, Null}
True
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With