Python - an easy way to "compare" map one array to another

I have an array a = [1, 2, 3, 4, 5, 6] and b = [1, 3, 5] , and I would like to display a in such a way that for each element from a between the elements in b it will be mapped to index b is the top range that contains a . Not the best explanation in words, but an example

 a = 1 -> 0 because a <= first element of b a = 2 -> 1 because b[0] < 2 <= b[1] and b[1] = 3 a = 3 -> 1 a = 4 -> 2 because b[1] < 4 <= b[2] 

So the final product I want is f(a, b) = [0, 1, 1, 2, 2, 2]

I know that I can just go in cycles and decide for it, but I was wondering if there is a smart, fast (vectorized) way to do this in pandas / numpy

+5
source share
2 answers

Use python bisect module:

 from bisect import bisect_left a = [1, 2, 3, 4, 5, 6] b = [1, 3, 5] def f(_a, _b): return [bisect_left(_b, i) for i in _a] print(f(a, b)) 

bisect - array log division algorithm

This module provides support for maintaining a list in sorted order without sorting the list after each insertion. For long item lists with expensive comparative operations, this can be an improvement over the more common approach. The module is called bisect because it uses the basic bisection algorithm to do its job. The source code may be most useful as a working example of an algorithm (the boundary conditions are already correct!).

The following functions are provided:

bisect.bisect_left(a, x, lo=0, hi=len(a))

Find the insertion point for x in a to keep the sorted order. The parameters lo and hi can be used to indicate a subset of the list to consider; the whole list is used by default. If x is already present in a, the entry point will be in front of (to the left) all existing elements. The return value is suitable for use as the first parameter for list.insert() , assuming a is already sorted.

The returned insertion point I splits the array a into two halves so that all(val < x for val in a[lo:i]) for the left side and all(val >= x for val in a[i:hi]) side.

Link: https://docs.python.org/3/library/bisect.html

+7
source

bisect faster: solution assumes lists are sorted

 a = [1, 2, 3, 4, 5, 6] b = [1, 3, 5] inds=[min(bisect_left(b,x),len(b)-1) for x in a] 

returns

 [0, 1, 1, 2, 2, 2] 
+2
source

Source: https://habr.com/ru/post/1268845/


All Articles