On 5/06/2006 10:46 PM, Bruno Desthuilliers wrote: > [EMAIL PROTECTED] a écrit : >> hi >> in my code, i use dict(a) to make to "a" into a dictionary , "a" comes >> from user input, so my program does not know in the first place. Then >> say , it becomes >> >> a = { '-A' : 'value1' , '-B' : "value2" , "-C" : "value3" , '-D' : >> 'value4' } >> >> somewhere next in my code, i will check for these..: >> >> 1) -A and -B cannot exist together >> 2) -A and -C cannot exist together >> 3) -A and -B and -D cannot exist together >> 4) and lots of other combinations to check for.... > > Looks like an option parser... If so, there's all you need in the > standard lib (look for the optparse module). > >> >> how can i efficiently check for the above? At first as i do simple >> checks , i use if and else. >> But as i began to check for more combinatoiuns, it gets messy.... > > First : use boolean logic (truth table, Kernaugh diagram, etc) to > simplify things. As an example, rule #3 is useless - it's a subset of > rule #1 (-A and -B and -D implies -A and -B). This should greatly reduce > the number of needed tests.
Good idea, but doesn't scale well. Simple code can weed out redundant rules, including any accidental duplicates that may creep into a long list. See code listing at end. > > Then, write a simple rule system describing either valid inputs or > invalid inputs (preferably the smallest set !-). FWIW, it can be as > simple as a list of lambdas/error messages pairs, with lambdas being > predicate taking dict keys as params: > > > _RULES = [ > (lambda keys : '-A' in keys and '-B' in keys, > "can't have both options -A and -B"), > (lambda keys : '-A' in keys and '-C' in keys, > "can't have both options -A and -C"), > # etc... > ] > The evil HR director won't let the PHB pay me on a per LOC basis, so I've had to come up with a compact table-driven approach :-) > def validate(options, rules): > keys = options.keys() > for predicate, message in rules: > if not predicate(keys): > raise ValueError(message) Cheers, John C:\junk>type option_combos.py bad_combos = ['ABD', 'AC', 'AB', 'CA'] def rule_compaction(bc_list, verbose=False): # The next few lines are admittedly oldfashioned :-) bc_sets = [set(x) for x in bc_list] deco = [(len(y), y) for y in bc_sets] deco.sort() bc_sets = [z[1] for z in deco] del deco if verbose: print "bc_sets #1:", bc_sets for k in xrange(len(bc_sets)-1, 0, -1): candidate = bc_sets[k] for ko in bc_sets[:k]: if ko <= candidate: if verbose: print candidate, "knocked out by", ko del bc_sets[k] break if verbose: print "bc_sets #2:", bc_sets return bc_sets option_rules = rule_compaction(bad_combos, verbose=True) def combo_disallowed_by(opt_set, rules): for rule in rules: if opt_set >= rule: return rule return None # redundantly, for emphasis if __name__ == "__main__": import sys for opt_string in sys.argv[1:]: failer = combo_disallowed_by(set(opt_string), option_rules) if failer: print repr(opt_string), "disallowed by", failer else: print repr(opt_string), "is OK" === a test === C:\junk>option_combos.py A AB AC AD BC ABD ABX XBA BX bc_sets #1: [set(['A', 'C']), set(['A', 'B']), set(['A', 'C']), set(['A', 'B', 'D'])] set(['A', 'B', 'D']) knocked out by set(['A', 'B']) set(['A', 'C']) knocked out by set(['A', 'C']) bc_sets #2: [set(['A', 'C']), set(['A', 'B'])] 'A' is OK 'AB' disallowed by set(['A', 'B']) 'AC' disallowed by set(['A', 'C']) 'AD' is OK 'BC' is OK 'ABD' disallowed by set(['A', 'B']) 'ABX' disallowed by set(['A', 'B']) 'XBA' disallowed by set(['A', 'B']) 'BX' is OK === the end === -- http://mail.python.org/mailman/listinfo/python-list