John Machin wrote: > 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.
Does it need to scale ? If there are lot of rules and frequently changing, yes, automating the process will be a good idea - but if it's about a program options, just using one's brain might be enough. At least it forces one to think about what's going on... > Simple code can weed out redundant > rules, Simple code can weed out redundant *simple* rules !-) (snip) >> 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 :-) <ot>I'm my own evil HR director and PHB !-)</ot> Don't like table-driven programming, John ? This solution takes very few lines, and while it's surely not a full-blown rule engine, it's at least reasonably flexible. (Not to say it's better than yours - it's of course a matter of effective use case). >> def validate(options, rules): >> keys = options.keys() >> for predicate, message in rules: >> if not predicate(keys): >> raise ValueError(message) > > > > 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 > Nice code - but how does it handle more complex predicates ? Seems you can only deal with 'and' rules here. <nitpick>"Doesn't scale well", you said ?-)</nitpick> (snip) -- bruno desthuilliers python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for p in '[EMAIL PROTECTED]'.split('@')])" -- http://mail.python.org/mailman/listinfo/python-list