check for dictionary keys

bruno at modulix onurb at xiludom.gro
Tue Jun 6 06:38:36 EDT 2006


John Machin wrote:
> On 5/06/2006 10:46 PM, Bruno Desthuilliers wrote:
> 
>> micklee74 at hotmail.com 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 'onurb at xiludom.gro'.split('@')])"



More information about the Python-list mailing list