2010-05-24 5 views
4

구현하는 데 가장 간단한 문제가 있습니다. 그러나 지금까지는 파이썬에서 해결책을 모색하지 못했습니다.찾아보기 테이블의 범위 내에서 값을 찾으십시오.

나는이 하나와 비슷한 테이블 구축 :

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

나는 그것이이 범위 내에있는 경우, 389 -> ASIA, 1300 -> LATAM, 5400 -> US보고 특정 값을 테스트합니다. 5409보다 큰 값은 검색 값을 반환하지 않아야합니다.

저는 일반적으로 일대일 일치를 가지고 있으며 조회를 위해 사전을 구현합니다.

하지만이 경우에는이 범위를 고려해야하며 문제를 해결할 방법이 없습니다.

아마도 전체 솔루션을 제공하지 않고 올바른 방향을 찾는데 도움이되는 의견을 제시해 주시겠습니까?

스프레드 시트의 경우 vlookup과 매우 유사합니다.

저는 파이썬 지식을 기초에서 중간 사이 어딘가에 설명합니다.

+1

숫자가 항상 소트

다음은이 작업을 수행하는 몇 가지 참신한 코드는? 'bisect'에 대해서는 – kennytm

답변

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입니다. –

3

먼저 정렬 된 인덱스를 만들 : 그럼

index = sorted(table.iteritems()) 

를 사용 키를 찾으려면 bisect를 사용하십시오.

_, 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 
관련 문제