5
$\begingroup$

I'm trying to make a function whose input is a list, and that outputs a list for which the nth element is the number of elements in the input less than n. So far, I have

l2 = Table[Length[Select[l1, # < n &]], {n, 1, M}]

Where l2 is the output list, l1 is the input list, and M is the desired length of l2. This gives the correct output, but is there a faster way to do this, as this function can get rather slow for larger lists.

An example of the function:

{2,2,3,3,7} —$>$ {0,0,2,4,4}.

$\endgroup$
2
  • $\begingroup$ Is your input list always sorted? $\endgroup$
    – Carl Woll
    Sep 22, 2019 at 17:25
  • $\begingroup$ Yes it is always sorted $\endgroup$
    – volcanrb
    Sep 22, 2019 at 17:36

3 Answers 3

6
$\begingroup$

The BoolEval package can be used here to get a good combination of performance and clean syntax:

<< BoolEval`
Table[BoolCount[list < n], {n, 5}]

{0, 0, 2, 4, 4}

$\endgroup$
6
$\begingroup$
list = RandomReal[{0, 100}, 100000];
Accumulate[BinCounts[list, {0, Ceiling[Max[list]], 1}]]
$\endgroup$
3
$\begingroup$
l1 = {2, 2, 3, 3, 7};
M = 4;
l2  = Table[Length[Select[l1, # < n &]], {n, 1, M}]

{0, 0, 2, 4}

UnitStep + Total

Total[1 - UnitStep[l1 - #] & /@ Range[M], {2}]
(* or Total[1 - UnitStep[l1 - #]] & /@ Range[M] *)

{0, 0, 2, 4}

Clip + Unitize + Total

Total[1 - Unitize@Clip[l1, {#, ∞}, {0, 1}] & /@ Range[ M], {2}]
(* or Total[1 - Unitize @ Clip[l1, {#, ∞}, {0, 1}]] & /@ Range[M] *)

{0, 0, 2, 4}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.