【问题标题】:Find value within a range in lookup table在查找表中查找范围内的值
【发布时间】:2010-05-24 18:05:38
【问题描述】:

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

我已经建立了一个和这个类似的表:

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

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

我通常有一对一的匹配,并且会实现一个字典来进行查找。

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

也许在不提供完整解决方案的情况下,您能否提供一些帮助我寻找正确方向的 cmets?

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

我会将我的 Python 知识描述为介于基础到中级之间。

【问题讨论】:

  • 数字是否总是排序的?

标签: python lookup


【解决方案1】:

您可以使用 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')

【讨论】:

    【解决方案2】:

    先做一个排序索引:

    index = sorted(table.iteritems())
    

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

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

    【讨论】:

      【解决方案3】:
      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
      

      【讨论】:

        【解决方案4】:

        如果您只有 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]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-15
          • 1970-01-01
          • 1970-01-01
          • 2019-12-31
          • 1970-01-01
          相关资源
          最近更新 更多