check for dictionary keys
John Machin
sjmachin at lexicon.net
Tue Jun 6 03:10:06 CEST 2006
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. 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 ===
More information about the Python-list
mailing list