Hash a Range of Values

前端 未结 4 1135

I know that I can hash singular values as keys in a dict. For example, I can hash 5 as one of the keys in a dict.

I am current

相关标签:
4条回答
  • 2020-12-10 15:12

    In order to improve the runtime, you could implement a bisection search.

    Otherwise you can put the interval-thresholds on a trie.

    EDIT: let me propose an implementation:

    class IntervalHash():
        def __init__(self,SortedList):
            #check it's sorted 
            self.MyList = []
            self.MyList.extend(SortedList) 
            self.lenlist = len(self.MyList)
        def get_interval(self,a):
            mylen = self.lenlist 
            mypos = 0
            while mylen > 1:
                mylen = (mylen/2 + mylen % 2)
                if mypos + mylen > self.lenlist - 1:
                    if self.MyList[self.lenlist - 1] < a:
                        mypos = self.lenlist - 1
                    break
                if self.MyList[mypos + mylen] < a:
                    mypos += mylen
            if mypos == 0:
                if self.MyList[0] > a: 
                    return ("-infty",self.MyList[0],0)
            if mypos == self.lenlist - 1:
                return (self.MyList[mypos],"infty",0)
            return (self.MyList[mypos],self.MyList[mypos+1],0)
    
    A = [0.32,0.70,1.13]
    MyHasher = IntervalHash(A)
    print "Intervals are:",A
    print 0.9 ," is in ",MyHasher.get_interval(0.9)
    print 0.1 ," is in ",MyHasher.get_interval(0.1)
    print 1.8 ," is in ",MyHasher.get_interval(1.8)
    

    further edits and improvements are welcome! The trie approach is much more involved, in my opinion it would be more appropriate for low level languages.

    0 讨论(0)
  • 2020-12-10 15:14

    As others have noted, the best algorithm you're going to get for this is something that's O(log N), not O(1), with something along the lines of a bisection search through a sorted list.

    The easiest way to do this in Python is with the bisect standard module, http://docs.python.org/library/bisect.html. Note, in particular, the example in section 8.5.2 there, on doing numeric table lookups -- it's exactly what you are doing:

    >>> def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
    ...     i = bisect(breakpoints, score)
    ...     return grades[i]
    ...
    >>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
    ['F', 'A', 'C', 'C', 'B', 'A', 'A']
    

    Replace the grades string with a list of functions, the breakpoints list with your list of lower thresholds, and there you go.

    0 讨论(0)
  • 2020-12-10 15:15

    If your intervals are regular, you can scale and then floor your operands to the minimum of each range, then pass that result directly into a dict mapping those lower bounds to the appropriate handler.

    An example implementation, using the ranges you provided.

    # Integerize our 0.1 width intervals; scale by x10
    handlerDict = {}
    handlerDict[0] = lambda x: ... # 0.1
    handlerDict[1] = lambda x: ... # 0.2
    handlerDict[2] = lambda x: ... # 0.3
    ...
    
    # Get the right handler, scaling x by x10; handle
    handlerDict[int(10*x)](x, ...)
    
    0 讨论(0)
  • 2020-12-10 15:19

    You don't necessarily need to hash an entire range of values. For example, in the scale given above, if you were given 0.15, you can round it up to the 0.2 (the first digit after decimal point), and hash 0.2 instead.

    How efficient does this have to be? An alternative you can try is a binary search. Have the interval values stores in sorted order in a list, and do binary search on it. For example:

    sorted_list = [ (0.1, function1), (0.2, function2), ....(0.6, function6) ] 
    

    Then you simply do binary search to find the smallest element that is bigger than x. This will yield O(log(n)).

    0 讨论(0)
提交回复
热议问题