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 _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor