# How do I count the number of elements in a list which are between two determined values?

I have a long list (apprx. 10000 elements) of numbers. I want to count the number of elements between two determined vallues a and b.

For example, consider the list:

0.38591
0.05216
0.3482
0.88671
0.16251
0.46188
0.91803
0.40279
0.31246
0.80954
0.40326
1.291
0.55321


and a=0.3 and b=0.6

n = 10000;
list = RandomReal[{0, 1}, n];
a = 0.3;
b = 0.6;
UnitStep[list - a].UnitStep[b - list]


This isn't as fast as the UnitStep method given by Henrik, but for many applications having the most efficient method isn't necessary.

Length @ Select[list, Between[{a, b}]]


or

Count[list, _?(Between[{a, b}])]

Total@Boole[a <= # <= b & /@ list]


If you are trying to do this operation repeatedly for the same list but different endpoints, then a faster alternative is to use Nearest. The basic idea is the following (I increased the size of the random list so that the speed difference is more readily apparent):

SeedRandom
list=RandomReal[{0,1}, 10^5];
nf = Nearest[Sort @ list -> "Index"]; //AbsoluteTiming
nf[.6] - nf[.3] //RepeatedTiming


{0.015579, Null}

{4.97*10^-6, {29950}}

as compared to Henrik's solution:

UnitStep[list-a].UnitStep[b-list] //RepeatedTiming


{0.00025, 29950}

The time to create the nearest function is rather large, but it only needs to be done once. The application of the nearest functions is extremely fast.

However, although for this example the two approaches agree, the Nearest approach doesn't quite work because the nearest point may be lower or greater than the endpoint selected. So, a more refined approach that accounts for this fuzziness is the following:

InbetweenCount[list_] := With[{slist = Sort @ list},
InbetweenCountFunction[slist, Nearest[slist -> "Index"]]
]

InbetweenCountFunction[list_, nf_][{left_, right_}] := With[
{
l = First @ nf[left],
r = First @ nf[right]
},
r - l + Switch[Sign[list[[{l, r}]] - {left, right}],
{1,-1}, 1,
{-1,1}, -1,
_, 0
]
]


This is how the above code would be used:

icf = InbetweenCount[list]; //AbsoluteTiming
icf[{.3, .6}] //RepeatedTiming


{0.014189, Null}

{0.0000114, 29950}

Notice that the creation of the InbetweenCountFunction takes nontrivial time. However, it's application is very fast.

It is possible to vectorize the InbetweenCountFunction so that it works on a list of {left, right} pairs to obtain a further speed improvement.

(Not as fast as that by Henrik)

Count[Clip[list, {a, b}, {0., 0.}], Except[0.]]


You can also use BinCounts using {{a,b}} as bin specification:

BinCounts[list, {{a, b}}]


or a combination of Clip, Unitize and Total:

Total @ Unitize @ Clip[list, {a, b}, {0, 0}]


Note: This is slower than Henrik's approach using Dot+ UnitStep combination.