[Tutor] value range checker

Albert-Jan Roskam sjeik_appie at hotmail.com
Wed Aug 26 15:19:16 CEST 2015


Hello,


I have a written a function checks the validity of values. The ranges of valid values are stored in a database table.

Such a table contains three columns: category, min and max. One record of such a table specifies the range for

a certain category, but a category may be spread out over multiple records.


For example, the category-min-max tuples

("cat a", 1, 1), 

("cat a", 3, 3), 

("cat a", 6, 10),

correspond to a range of category A of 1-1, 3-3, 6-10, which is the same as 1, and 3, and 6, 7, 8, 9, 10.


The code below does exactly what I want:


import collections
import bisect
import math
import pprint


def get_valid_value_lookup(records):
    """
    Translates value range information (from a database table)
    into a dictionary of the form {<category>: [<range of accepted values>]}
    """
    Boundaries = collections.namedtuple("Boundaries", "category min max")
    records = [Boundaries(*record) for record in records]
    boundaries = collections.defaultdict(list)
    crap = [boundaries[record.category].__iadd__(range(record.min, record.max + 1))
            for record in records]
    return dict(boundaries)


def is_valid(lookup, category, value):
    """Return True if value is member of a list of a given category, False otherwise."""
    try:
        return value in lookup[category]
    except KeyError:
        raise KeyError("Invalid category: %r" % category)


def is_valid2(lookup, category, value):
    """Return True if value is member of a list of a given category, False otherwise."""
    # this version also knows how to deal with floats.

    try:

         L = lookup[category]
    except KeyError:
        raise KeyError("Invalid category: %r" % category)

    adjusted_value = value if int(value) in (L[0], 0, L[-1]) else math.ceil(value)
    try:
        chopfunc = bisect.bisect_right if value < L[0] else bisect.bisect_left
        return L[chopfunc(L, value)] == adjusted_value
    except IndexError:
        return False


if __name__ == '__main__':
    L = [("cat a", 1, 1), ("cat a", 3, 3), ("cat a", 6, 10),
         ("cat b", 1, 9), ("cat c", 1, 2), ("cat c", 5, 9)]
    lookup = get_valid_value_lookup(L)
    assert not is_valid(lookup, "cat a", 999) # value 999 is invalid for category 1
    assert is_valid(lookup, "cat a", 10)
    assert not is_valid2(lookup, "cat a", 0.1)
    assert not is_valid2(lookup, "cat a", -1)
    assert is_valid2(lookup, "cat a", 6.1)


    L2 = [(1, -5, 1), (1, 3, 3), (1, 6, 10), (2, 1, 9), (3, 1, 2), (3, 5, 9)]
    lookup = get_valid_value_lookup(L2)
    assert is_valid2(lookup, 1, -4.99)
    assert is_valid2(lookup, 1, -5)


My questions:

[1] @ is_valid: is there a better way to do this? I mostly don't like the use of the __iadd__ dunder method. 

[2] @ is_valid2: Perhaps an answer to my previous question. Is this a better approach? 

[3] I am inheriting a this system. It feels a bit strange that these range check values are stored in a database. 

Would yaml be a better choice? Some of the tables are close to 200 records.


Thank you in advance!


Albert-Jan 		 	   		  


More information about the Tutor mailing list