splitting one dictionary into two

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • jsaul

    splitting one dictionary into two

    Hello all,

    I have to split a dict into two dicts. Depending on their values,
    the items shall remain in the original dict or be moved to another
    one and at the same time be removed from the original dict.

    OK, this is how I do it right now:

    dict1 = { "a":1, "b":3, "c":5, "d":4, "e":2 }
    dict2 = {}
    klist = []

    for key in dict1:
    if dict1[key] > 3: # some criterion
    dict2[key] = dict1[key]
    klist.append(ke y)

    for key in klist:
    del dict1[key]

    print dict1
    print dict2

    That means that I store the keys of the items to be removed from
    the original dict in a list (klist) and subsequently remove the
    items using these keys.

    Is there an "even more pythonic" way?

    Cheers, jsaul
  • wes weston

    #2
    Re: splitting one dictionary into two

    jsaul wrote:[color=blue]
    > Hello all,
    >
    > I have to split a dict into two dicts. Depending on their values,
    > the items shall remain in the original dict or be moved to another
    > one and at the same time be removed from the original dict.
    >
    > OK, this is how I do it right now:
    >
    > dict1 = { "a":1, "b":3, "c":5, "d":4, "e":2 }
    > dict2 = {}
    > klist = []
    >
    > for key in dict1:
    > if dict1[key] > 3: # some criterion
    > dict2[key] = dict1[key]
    > klist.append(ke y)
    >
    > for key in klist:
    > del dict1[key]
    >
    > print dict1
    > print dict2
    >
    > That means that I store the keys of the items to be removed from
    > the original dict in a list (klist) and subsequently remove the
    > items using these keys.
    >
    > Is there an "even more pythonic" way?
    >
    > Cheers, jsaul[/color]

    jsaul,
    I'll have a hack with small code. Nice that you can
    iterate while removing.
    wes


    dict1 = { "a":1, "b":3, "c":5, "d":4, "e":2 }
    dict2 = {}

    print dict1

    for key,val in dict1.items():
    if val > 3: # some criterion
    dict2[key] = val
    del dict1[key]

    print dict1
    print dict2

    Comment

    • Peter Otten

      #3
      Re: splitting one dictionary into two

      jsaul wrote:
      [color=blue]
      > I have to split a dict into two dicts. Depending on their values,
      > the items shall remain in the original dict or be moved to another
      > one and at the same time be removed from the original dict.
      >
      > OK, this is how I do it right now:
      >
      > dict1 = { "a":1, "b":3, "c":5, "d":4, "e":2 }
      > dict2 = {}
      > klist = []
      >
      > for key in dict1:
      > if dict1[key] > 3: # some criterion
      > dict2[key] = dict1[key]
      > klist.append(ke y)
      >
      > for key in klist:
      > del dict1[key]
      >
      > print dict1
      > print dict2
      >
      > That means that I store the keys of the items to be removed from
      > the original dict in a list (klist) and subsequently remove the
      > items using these keys.
      >
      > Is there an "even more pythonic" way?[/color]

      Only a minor change to do away with the temporary list:

      for key in dict1:
      if dict1[key] > 3: # some criterion
      dict2[key] = dict1[key]

      for key in dict2:
      del dict1[key]

      Peter

      Comment

      • Larry Bates

        #4
        Re: splitting one dictionary into two

        There a quite a few different ways to do this, but
        I might suggest something like:

        dict1={"a":1, "b":3, "c":5, "d":4, "e":2}
        dict2={}
        dict3={}
        [dict2.setdefaul t(k,v) for k,v in dict1.items() if v > 3]
        [dict3.setdefaul t(k,v) for k,v in dict1.items() if not v > 3]
        dict1=dict3.cop y()

        Very "Pythonic" but is 2 times slower than your original code.

        Another suggestion is:

        dict1 = { "a":1, "b":3, "c":5, "d":4, "e":2 }
        dict2 = {}

        keys=dict1.keys ()
        for key in keys:
        if dict1[key] > 3: # some criterion
        dict2[key] = dict1[key]
        del dict1[key]

        This is a "little" faster (100000 iterations of your method
        time=1.13 seconds, my method=0.94 seconds and I find easier
        to read (eliminates the unneeded klist variable and second
        loop).

        Larry Bates
        Syscon, Inc.

        "jsaul" <use_reply-to@empty.invali d> wrote in message
        news:2004040115 3103.GC4577@jsa ul.de...[color=blue]
        > Hello all,
        >
        > I have to split a dict into two dicts. Depending on their values,
        > the items shall remain in the original dict or be moved to another
        > one and at the same time be removed from the original dict.
        >
        > OK, this is how I do it right now:
        >
        > dict1 = { "a":1, "b":3, "c":5, "d":4, "e":2 }
        > dict2 = {}
        > klist = []
        >
        > for key in dict1:
        > if dict1[key] > 3: # some criterion
        > dict2[key] = dict1[key]
        > klist.append(ke y)
        >
        > for key in klist:
        > del dict1[key]
        >
        > print dict1
        > print dict2
        >
        > That means that I store the keys of the items to be removed from
        > the original dict in a list (klist) and subsequently remove the
        > items using these keys.
        >
        > Is there an "even more pythonic" way?
        >
        > Cheers, jsaul[/color]


        Comment

        • Terry Reedy

          #5
          Re: splitting one dictionary into two


          "jsaul" <use_reply-to@empty.invali d> wrote in message
          news:2004040115 3103.GC4577@jsa ul.de...[color=blue]
          > Hello all,
          >
          > I have to split a dict into two dicts. Depending on their values,
          > the items shall remain in the original dict or be moved to another
          > one and at the same time be removed from the original dict.
          >
          > OK, this is how I do it right now:
          >
          > dict1 = { "a":1, "b":3, "c":5, "d":4, "e":2 }
          > dict2 = {}
          > klist = []
          >
          > for key in dict1:
          > if dict1[key] > 3: # some criterion
          > dict2[key] = dict1[key]
          > klist.append(ke y)
          >
          > for key in klist:
          > del dict1[key]
          >
          > print dict1
          > print dict2
          >
          > That means that I store the keys of the items to be removed from
          > the original dict in a list (klist) and subsequently remove the
          > items using these keys.
          >
          > Is there an "even more pythonic" way?[/color]

          Delete klist stuff and do deletion with

          for key in dict2: del dict1[key]

          tjr




          Comment

          • jsaul

            #6
            Re: splitting one dictionary into two

            * Peter Otten [2004-04-01 18:46]:[color=blue]
            > jsaul wrote:
            >[color=green]
            > > dict1 = { "a":1, "b":3, "c":5, "d":4, "e":2 }
            > > dict2 = {}
            > > klist = []
            > >
            > > for key in dict1:
            > > if dict1[key] > 3: # some criterion
            > > dict2[key] = dict1[key]
            > > klist.append(ke y)
            > >
            > > for key in klist:
            > > del dict1[key]
            > >
            > > print dict1
            > > print dict2[/color]
            >
            > Only a minor change to do away with the temporary list:
            >
            > for key in dict1:
            > if dict1[key] > 3: # some criterion
            > dict2[key] = dict1[key]
            >
            > for key in dict2:
            > del dict1[key][/color]

            Hi Peter and others who responded so quickly,

            I notice now that I forgot to mention an important condition,
            namely that in real life dict2 is already existing and may have
            become huge. That's the reason why I need to somewhere save only
            those items which I most recently removed from the 1st dict, as
            I want to avoid iterating over the while dict2. In real life,
            dict1 contains pending jobs which, after they are done, are moved
            to a second dict for post processing.

            Sorry for the confusion.

            I think the most "pythonic" candidate is actually the version
            suggested by Larry, namely

            dict1 = { "a":1, "b":3, "c":5, "d":4, "e":2 }
            dict2 = {} # in real life, dict2 already exists

            for key in dict1.keys():
            if dict1[key] > 3:
            dict2[key] = dict1.pop(key)

            print dict1
            print dict2

            Cheers, jsaul

            Comment

            • wes weston

              #7
              Re: splitting one dictionary into two

              jsaul wrote:[color=blue]
              > I notice now that I forgot to mention an important condition,
              > namely that in real life dict2 is already existing and may have
              > become huge.[/color]

              jsaul,
              How huge is huge?
              wes

              Comment

              • Peter Abel

                #8
                Re: splitting one dictionary into two

                jsaul <use_reply-to@empty.invali d> wrote in message news:<200404011 53103.GC4577@js aul.de>...[color=blue]
                > Hello all,
                >
                > I have to split a dict into two dicts. Depending on their values,
                > the items shall remain in the original dict or be moved to another
                > one and at the same time be removed from the original dict.
                >
                > OK, this is how I do it right now:
                >
                > dict1 = { "a":1, "b":3, "c":5, "d":4, "e":2 }
                > dict2 = {}
                > klist = [][/color]

                klist is not necessary because key in dict1 will give you the
                same but faster.
                [color=blue]
                >
                > for key in dict1:
                > if dict1[key] > 3: # some criterion
                > dict2[key] = dict1[key]
                > klist.append(ke y)
                >
                > for key in klist:
                > del dict1[key]
                >
                > print dict1
                > print dict2
                >
                > That means that I store the keys of the items to be removed from
                > the original dict in a list (klist) and subsequently remove the
                > items using these keys.
                >
                > Is there an "even more pythonic" way?
                >
                > Cheers, jsaul[/color]

                One solution could be:[color=blue][color=green][color=darkred]
                >>> dict1 = { "a":1, "b":3, "c":5, "d":4, "e":2 }[/color][/color][/color]
                # a little transfer-function, which deletes an item (k,v) in d and
                # returns (k,v)[color=blue][color=green][color=darkred]
                >>> transfer=lambda d,(k,v):[d.__delitem__(k )] and (k,v)[/color][/color][/color]
                # transfer the items from one dict into a list and make a dict
                # from it on the fly[color=blue][color=green][color=darkred]
                >>> dict2=dict([transfer(dict1, (k,v)) for (k,v) in dict1.items() if v>3])
                >>> dict1[/color][/color][/color]
                {'a': 1, 'b': 3, 'e': 2}[color=blue][color=green][color=darkred]
                >>> dict2[/color][/color][/color]
                {'c': 5, 'd': 4}[color=blue][color=green][color=darkred]
                >>>[/color][/color][/color]

                Regards
                Peter

                Comment

                Working...