2017-06-14 76 views
5

我有一个数组a = [1, 2, 3, 4, 5, 6]b = [1, 3, 5],我想映射a使得对于a每一个元素,在b元素之间是它会被映射到的b指数是上范围的a包含在,不是在口头上最好的解释,但这里有一个例子Python的 - 简单的方法来“比较”映射一个阵列到另一个

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] 

所以最终的产品我想是f(a, b) = [0, 1, 1, 2, 2, 2]

我知道我只需循环,解决它,但我不知道是否有是一个聪明,快速(矢量)的方式来做到这一点的大熊猫/ numpy的

+0

是那些阵列总是嘱咐? – taras

+0

是的,你可以假定他们是有序的。也可以假设b中的每个元素都包含在一个(没有这个约束的更一般的解决方案将是太棒了,但我认为它更容易) – Michael

回答

7

使用Python的bisect模块:

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,因为它使用基本的二分法算法来完成其工作。源代码可能是最有用的算法的实例(边界条件已经正确!)。提供

以下功能:

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

在找到一个X插入点维持有序。可以使用参数lohi来指定应该考虑的列表的子集;默认情况下使用整个列表。如果x已存在于a中,则插入点将位于任何现有条目之前(的左侧)。 假设a已被排序,返回值适合用作list.insert()的第一个参数。

返回的插入点分区阵列一个分为两半,使得all(val < x for val in a[lo:i])用于左侧和all(val >= x for val in a[i:hi])为右侧。

参考: https://docs.python.org/3/library/bisect.html

2

开张快:该解决方案假定列表进行排序

a = [1, 2, 3, 4, 5, 6] 
b = [1, 3, 5] 

inds=[min(bisect_left(b,x),len(b)-1) for x in a] 

回报

[0, 1, 1, 2, 2, 2] 
相关问题