How could I use BinLists to give elements indices in list instead of giving the list elements belonging to each bin ?
Thanks.
How could I use BinLists to give elements indices in list instead of giving the list elements belonging to each bin ?
Thanks.
using the 2d form of BinLists ( note the first dimension binspec is cooked up so there is just one bin )
list = RandomReal[{0, 1}, {20}];
binspec = {0, 1, .1};
(#[[All, 1]] & /@ First@BinLists[ MapIndexed[{First@#2, #} &, #] ,
{0, Length@# + 1, Length@# + 1}, binspec]) &@list
{{1, 10, 20}, {6}, {7, 15}, {4}, {5, 12, 17}, {11}, {14, 18}, {9}, {2, 3, 8, 16, 19}, {13}}
( list[[#]] & /@ % ) == BinLists[ list , binspec]
True
You could simply do this as well:
Union@Flatten@(Position[ list, #] & /@ # ) & /@ BinLists[list, binspec]
Using the function positionDuplicates from this answer by @Szabolcs
ClearAll[positionDuplicates, dispatchF, positionBins]
positionDuplicates[list_] := GatherBy[Range@Length[list], list[[#]] &];
dispatchF = Dispatch @ Thread[DeleteDuplicates[#] -> positionDuplicates[#]] &;
positionBins = Union @@@ (BinLists[#, #2] /. dispatchF[#1]) &;
Example 1:
data = RandomInteger[5, 17]
{5, 4, 1, 3, 0, 3, 0, 0, 5, 5, 0, 0, 5, 1, 5, 5, 0}
BinLists[data, 3] (* change `3` to your choice of binspecs *)
{{}, {1, 0, 0, 0, 0, 0, 1, 0}, {5, 4, 3, 3, 5, 5, 5, 5, 5}}
positionBins[data, 3]
{{}, {3, 5, 7, 8, 11, 12, 14, 17}, {1, 2, 4, 6, 9, 10, 13, 15, 16}}
Example 2:
BinLists[data, {{0, 2, 4, 6}}]
{{1, 0, 0, 0, 0, 0, 1, 0}, {3, 3}, {5, 4, 5, 5, 5, 5, 5}}
positionBins[data, {{0, 2, 4, 6}}]
{{3, 5, 7, 8, 11, 12, 14, 17}, {4, 6}, {1, 2, 9, 10, 13, 15, 16}}
For my own question and self-answer I wrote the following utility function.
BinPositions[vals_, brakes_, sameTest_] :=
Map[val \[Function]
Catch@Module[{lo = 1, mid, hi = Length[brakes], el, res},
While[lo <= hi, Which[
TrueQ@sameTest[val, el = brakes[[mid = Floor[(lo + hi)/2]]]],
Throw[mid],
el > val, hi = mid - 1,
True, lo = mid + 1]];
lo - 1/2],
vals]
The semanthic is sligtly different from previous answer, but, maybe, it can be adapted to your scenario.
list = RandomReal[{0, 100}, {20}]
brakes = Union@RandomInteger[{0, 100}, 10]
Floor@BinPositions[list, brakes, SameQ]
{48.311, 40.7217, 50.8321, 73.2729, 24.7769, 42.4868, 12.475, 7.04288, 3.22704, 89.9731, 82.0066, 73.565, 83.0642, 45.4985, 81.3878, 55.5902, 82.3677, 68.8531, 57.4473, 83.1311}
{6, 20, 28, 32, 35, 52, 73, 82, 95}
{5, 5, 5, 7, 2, 5, 1, 1, 0, 8, 8, 7, 8, 5, 7, 6, 8, 6, 6, 8}