On Sep 8, 10:20 am, John Machin <[EMAIL PROTECTED]> wrote: > On Sep 8, 10:47 am, MK Bernard <[EMAIL PROTECTED]> wrote: > > > > > On Sep 7, 3:37 pm, John Machin <[EMAIL PROTECTED]> wrote: > > > > On Sep 8, 7:51 am, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> 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. -- http://mail.python.org/mailman/listinfo/python-list