在查找表中查找范围内的值

时间:2010-05-24 18:05:38

标签: python lookup

我有最简单的问题需要实现,但到目前为止,我还没有能够解决Python中的解决方案。

我已经构建了一个类似于这个的表:

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

我会测试某个值,看它是否属于这些范围389 -> ASIA, 1300 -> LATAM, 5400 -> US。大于5409的值不应返回查找值。

我通常有一对一的匹配,并会为查找实现字典。

但在这种情况下,我必须考虑这些范围,而我并没有找到解决问题的方法。

也许没有提供整个解决方案,您能否提供一些有助于我朝着正确方向前进的评论?

它与电子表格中的vlookup非常相似。

我会将我的Python知识描述为从基础到中间的某个地方。

4 个答案:

答案 0 :(得分:14)

您可以使用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 :(得分:3)

首先制作一个排序索引:

index = sorted(table.iteritems())

然后,使用bisect找到你的密钥:

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

答案 2 :(得分: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]

答案 3 :(得分: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
相关问题