Updating python dictionary

andyhume at gmail.com andyhume at gmail.com
Mon Sep 8 22:12:03 CEST 2008


On Sep 8, 10:20 am, John Machin <sjmac... at lexicon.net> wrote:
> On Sep 8, 10:47 am, MK Bernard <mkbernard.... at gmail.com> wrote:
>
>
>
> > On Sep 7, 3:37 pm, John Machin <sjmac... at lexicon.net> wrote:
>
> > > On Sep 8, 7:51 am, "andyh... at gmail.com" <andyh... at gmail.com> wrote:
>
> > > > Hello...
>
> > > > I have a dict of key/values and I want to change the keys in it, based
> > > > on another mapping dictionary. An example follows:
>
> > > > MAPPING_DICT = {
> > > >     'a': 'A',
> > > >     'b': 'B',
>
> > > > }
>
> > > > my_dict = {
> > > >     'a': '1',
> > > >     'b': '2'
>
> > > > }
>
> > > > I want the finished my_dict to look like:
>
> > > > my_dict = {
> > > >     'A': '1',
> > > >     'B': '2'
>
> > > > }
>
> > > > Whereby the keys in the original my_dict have been swapped out for the
> > > > keys mapped in MAPPING_DICT.
>
> > > > Is there a clever way to do this, or should I loop through both,
> > > > essentially creating a brand new dict?
>
> > > Is this homework?
>
> > > There seems to be an implicit assumption in the answers so far that
> > > your mapping is a 1:1 mapping of all possible input keys.
>
> > > If it doesn't include all possible input keys, answers will crash with
> > > a KeyError. If there are any many:1 elements in the mapping (for
> > > example, {'a': 'A', 'b': 'A'}), lossage happens. You may wish to code
> > > in some checks for this.
>
> > Thats exactly why I did an explicit check in my post, so as to make
> > sure that such a collision could not occur. It would seem that
> > something along what I posted would be safer, if less elegant, than
> > the others.
>
> I noted two problems:
> (1) not covering all input keys: your code explicitly sweeps this
> problem under the carpet, and does it laboriously ...
>     if x in my_dict.keys():
> instead of
>     if x in my_dict:
> (2) not a 1:1 mapping -- for example, 'a' and 'b' both map to 'A' (the
> only "collision" that I can see), but you don't address that.
>
> Here's some code which attempts to cover the bases:
>
> new_dict = {}
> for key in my_dict:
>     if key not in MAPPING_DICT:
>         raise NoMapError('blah %r' % key)
>     else:
>         new_key = MAPPING_DICT[key]
>     if new_key in new_dict:
>         raise ManyToOneError('gurgle %r waffle %r' % (key, new_key))
>     else:
>         new_dict[new_key] = my_dict[key]
>
> Having considered what is actually required under the checked-for
> conditions, one or both raise statements may be replaced by other
> code, and then simplified e.g. the first 4 lines in the loop may end
> up being replaced by
>     new_key = MAPPING_DICT.get(key, key)
> as already suggested by one respondent.
>
> Note that useful use-cases for any variety of this key-change exercise
> may have many more items in MAPPING_DICT than there are in my_dict (a
> big language dictionary and a few fragments of text to be
> "translated"), or vice versa (a small synonym dictionary (color ->
> colour, center -> centre) and a big input to be "standardised") so
> it's a good idea to inquire which is likely to be the smaller and
> iterate over that if the requirements permit it.

In the interests of academia (although this isn't homework :)) I'll
answer some of those questions:

- Yes, the mapping dict doesn't necessarily have the same number of
entries as the my_dict. It may have less than it or more than it.
- There will never be dupes of key or value in the mapping. Though
there maybe in my_dict.

And, for extra credit, it may be useful to be able to 'translate' the
my_dict back again using the same mapping_dict. ie, using the values
in mapping dict as the new keys in my_dict, and the keys as the new
values.

Andy.



More information about the Python-list mailing list