2010-05-24 59 views
4

我有最簡單的問題來實現,但到目前爲止,我還沒有能夠在Python中解決問題。在查找表中找到範圍內的值

我建立了一個表,看起來與此類似:

501 - ASIA 
1262 - EUROPE 
3389 - LATAM 
5409 - US 

我會測試某個值,看它是否在這些範圍內,389 -> ASIA, 1300 -> LATAM, 5400 -> US。大於5409的值不應返回查找值。

我通常有一對一的匹配,並且會實現查找字典。

但在這種情況下,我必須考慮這些範圍,而且我沒有看到我擺脫問題的方法。

也許沒有提供整體解決方案,您能否提供一些意見,以幫助我尋找正確的方向?

它與電子表格中的vlookup非常相似。

我會將我的Python知識描述爲介於基本到中間之間的某處。

+1

是數字總是排序? – kennytm 2010-05-24 18:07:13

回答

13

您可以使用bisect模塊。相反,線性搜索,那會使用二進制搜索,這將有望更快:

import bisect 

places = [ 
    (501, 'ASIA'), 
    (1262, 'EUROPE'), 
    (3389, 'LATAM'), 
    (5409, 'US'), 
] 
places.sort() # list must be sorted 

for to_find in (389, 1300, 5400): 
    pos = bisect.bisect_right(places, (to_find,)) 
    print '%s -> %s' % (to_find, places[pos]) 

會打印:

389 -> (501, 'ASIA') 
1300 -> (3389, 'LATAM') 
5400 -> (5409, 'US') 
+1

+1對'bisect'。 – 2010-05-24 18:35:55

3

首先做一個排序索引:

index = sorted(table.iteritems()) 

然後,使用平分找到你的鑰匙:

_, value = bisect.bisect_left(index, (key, '')) 
2

如果您只有5409個值,我只需將每個整數放入字典中的範圍並進行正常查找。每個條目需要12個字節,總數只是500Kb,所以爲什麼要麻煩。

下面是一些巧妙的代碼來做到這一點:

places = [ 
    (501, 'ASIA'), 
    (1262, 'EUROPE'), 
    (3389, 'LATAM'), 
    (5409, 'US'), 
] 

def make_zones(borders): 
    last = 0 
    for n,v in borders: 
     for i in range(last, n+1): 
      yield i,v 
     last = i+1 

zones = dict(make_zones(places)) 

print zones[501], zones[502] 
2
places = [(501,"ASIA"),(1262,"EUROPE"),(3389,"LATAM"),(5409,"US")] 
places.sort() 

def getSection(places,requests): 
    PL= len(places) 
    LAST=places[-1][0] 
    for R in requests: 
     for P in range(PL): 
      if not (R < 0 or R>LAST):#keep away integers out of range 
       if R<=places[P][0]: 
        print R,"->",places[P][1] 
        break 
      else: 
       break 

到getSection一個電話,

getSection(places,(5000000,389,1300,5400,-1,6000)) 

給出:

389 -> ASIA 
1300 -> LATAM 
5400 -> US