check for dictionary keys

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • micklee74@hotmail.com

    #1

    check for dictionary keys

    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.

  • faulkner

    #2
    Re: check for dictionary keys

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

    micklee74@hotma il.com wrote:[color=blue]
    > 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.[/color]

    Comment

    • Bruno Desthuilliers

      #3
      Re: check for dictionary keys

      micklee74@hotma il.com a écrit :[color=blue]
      > 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....[/color]

      Looks like an option parser... If so, there's all you need in the
      standard lib (look for the optparse module).
      [color=blue]
      >
      > 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....[/color]

      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(option s, rules):
      keys = options.keys()
      for predicate, message in rules:
      if not predicate(keys) :
      raise ValueError(mess age)

      Comment

      • John Machin

        #4
        Re: check for dictionary keys

        On 5/06/2006 10:46 PM, Bruno Desthuilliers wrote:[color=blue]
        > micklee74@hotma il.com a écrit :[color=green]
        >> 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....[/color]
        >
        > Looks like an option parser... If so, there's all you need in the
        > standard lib (look for the optparse module).
        >[color=green]
        >>
        >> 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....[/color]
        >
        > 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.[/color]

        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.
        [color=blue]
        >
        > 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...
        > ]
        >[/color]

        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 :-)
        [color=blue]
        > def validate(option s, rules):
        > keys = options.keys()
        > for predicate, message in rules:
        > if not predicate(keys) :
        > raise ValueError(mess age)[/color]

        Cheers,
        John

        C:\junk>type option_combos.p y
        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_s ets)-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_disallowe d_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_disallowe d_by(set(opt_st ring), 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 ===

        Comment

        • bruno at modulix

          #5
          Re: check for dictionary keys

          John Machin wrote:[color=blue]
          > On 5/06/2006 10:46 PM, Bruno Desthuilliers wrote:
          >[color=green]
          >> micklee74@hotma il.com a écrit :
          >>[color=darkred]
          >>> 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....[/color]
          >>
          >>
          >> Looks like an option parser... If so, there's all you need in the
          >> standard lib (look for the optparse module).
          >>[color=darkred]
          >>>
          >>> 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....[/color]
          >>
          >>
          >> 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.[/color]
          >
          >
          > Good idea, but doesn't scale well.[/color]

          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...
          [color=blue]
          > Simple code can weed out redundant
          > rules,[/color]

          Simple code can weed out redundant *simple* rules !-)

          (snip)
          [color=blue][color=green]
          >> 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...
          >> ]
          >>[/color]
          >
          > 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 :-)[/color]

          <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).
          [color=blue][color=green]
          >> def validate(option s, rules):
          >> keys = options.keys()
          >> for predicate, message in rules:
          >> if not predicate(keys) :
          >> raise ValueError(mess age)[/color]
          >
          >
          >
          > C:\junk>type option_combos.p y
          > 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_s ets)-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
          >[/color]

          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@xiludom. gro'.split('@')])"

          Comment

          • John Machin

            #6
            Re: check for dictionary keys

            On 6/06/2006 8:38 PM, bruno at modulix wrote:[color=blue]
            > John Machin wrote:[color=green]
            >> On 5/06/2006 10:46 PM, Bruno Desthuilliers wrote:
            >>[color=darkred]
            >>> micklee74@hotma il.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.[/color]
            >>
            >> Good idea, but doesn't scale well.[/color]
            >
            > 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...
            >[color=green]
            >> Simple code can weed out redundant
            >> rules,[/color]
            >
            > Simple code can weed out redundant *simple* rules !-)
            >
            > (snip)
            >[color=green][color=darkred]
            >>> 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...
            >>> ]
            >>>[/color]
            >> 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 :-)[/color]
            >
            > <ot>I'm my own evil HR director and PHB !-)</ot>[/color]

            <ot> You must have some interesting conversations with yourself !-) </ot>
            [color=blue]
            >
            > Don't like table-driven programming, John ?[/color]

            I love table-driven programming. You seem to misunderstand; In this case
            the "bad combos" list *is* the table.
            [color=blue]
            >
            > 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).
            >[/color]
            [snip][color=blue]
            >
            > Nice code - but how does it handle more complex predicates ? Seems you
            > can only deal with 'and' rules here.[/color]

            More complex predicates are not in the OP's spec ... this is a defence I
            learned from somebody in this newsgroup recently :-)
            [color=blue]
            > <nitpick>"Doesn 't scale well", you
            > said ?-)</nitpick>[/color]

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

            Cheers,
            John

            Comment

            Working...