By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,053 Members | 922 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,053 IT Pros & Developers. It's quick & easy.

check for dictionary keys

P: n/a
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....

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....

thanks.

Jun 3 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a
def all(s):
for x in s:
if not x: return False
return True
bad_combos = [['-A', '-B'], ['-A', '-C'], ...]
for bad_combo in bad_combos:
assert not all([bad_elem in a for bad_elem in bad_combo])

mi*******@hotmail.com wrote:
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....

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....

thanks.


Jun 3 '06 #2

P: n/a
mi*******@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.

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...
]

def validate(options, rules):
keys = options.keys()
for predicate, message in rules:
if not predicate(keys):
raise ValueError(message)
Jun 5 '06 #3

P: n/a
On 5/06/2006 10:46 PM, Bruno Desthuilliers wrote:
mi*******@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 ===
Jun 6 '06 #4

P: n/a
John Machin wrote:
On 5/06/2006 10:46 PM, Bruno Desthuilliers wrote:
mi*******@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 'o****@xiludom.gro'.split('@')])"
Jun 6 '06 #5

P: n/a
On 6/06/2006 8:38 PM, bruno at modulix wrote:
John Machin wrote:
On 5/06/2006 10:46 PM, Bruno Desthuilliers wrote:
mi*******@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>


<ot> You must have some interesting conversations with yourself !-) </ot>

Don't like table-driven programming, John ?
I love table-driven programming. You seem to misunderstand; In this case
the "bad combos" list *is* the table.

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).
[snip]
Nice code - but how does it handle more complex predicates ? Seems you
can only deal with 'and' rules here.
More complex predicates are not in the OP's spec ... this is a defence I
learned from somebody in this newsgroup recently :-)
<nitpick>"Doesn't scale well", you
said ?-)</nitpick>


I understand 'scale' to relate to size, not to complexity.

Cheers,
John
Jun 6 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.