2017-06-14 75 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] 
相關問題