You could use a variation of my LeftNeighbor function, although it returns the left neighbor strictly less than the number instead of less equal as in your solution:
LeftNeighbor[s_]:=LeftNeighborFunction[s,Nearest[s->"Index"]]
LeftNeighbor[s_,list_List]:=LeftNeighbor[s][list]
LeftNeighbor[s_, elem_]:=First@LeftNeighbor[s][{elem}]
LeftNeighborFunction[s_,nf_][list_List]:=With[{n=nf[list][[All,1]]},n-UnitStep[s[[n]]-list]]
LeftNeighborFunction[s_,nf_][elem_]:=First @ LeftNeighborFunction[s,nf][{elem}]
MakeBoxes[i:LeftNeighborFunction[s_,nf_], StandardForm] ^:= Module[
{
len=Length[s],
g = FirstCase[ToBoxes[nf], _GraphicsBox, GraphicsBox[Point[{0,0}]],Infinity]
},
BoxForm`ArrangeSummaryBox[
LeftNeighborFunction,
i,
RawBoxes@g,
{
BoxForm`MakeSummaryItem[{"Data points: ",Length[s]},StandardForm],
BoxForm`MakeSummaryItem[{"Range: ",MinMax[s]},StandardForm]
},
{},
StandardForm,
"Interpretable"->True
]
]
Then:
L={1,2,5,7,8};
lnf = LeftNeighbor[L];
lnf[5]
lnf[Range[0, 9]]
2
{0, 0, 1, 2, 2, 2, 3, 3, 4, 5}
It should be possible to modify the code to return the left neighbor that is less equal than the requested number if desired.
A remark on performance
The construction of the LeftNeighborFunction
can be slow, but if you want to find the index of many numbers into the same list L
, then you will only have to construct the LeftNeighborFunction
once. Here is a comparison with a large list:
L = Sort @ RandomReal[100, 10^6];
The construction of the LeftNeightbor
is a bit slow:
lnf = LeftNeighbor[L]; //RepeatedTiming
{0.052, Null}
But finding the index of many numbers is very fast:
sample = RandomReal[100, 10^3];
r1 = lnf[sample]; //RepeatedTiming
{0.00020, Null}
Compare this with one of kglr's solution:
r2 = pos0[L, #]& /@ sample; //RepeatedTiming
{3.05, Null}
Check :
r1 === r2
True