2

I have a dictionary where i want to rename some of the dictionary keys which are lower case to camel case, but i want to maintain the sequence. Is there a way to maintain the integrity?

I am writing a cleanser which will aid with the same and it looks like this

def key_cleanser(data):
    name_cleanse_dict = {
        'id': 'ID',
        'emailid': 'emailId',
        'firstname': 'firstName',
        'middlename': 'middleName',
        'lastname': 'lastName',
        'addressline1': 'addressLine1',
        'addressline2': 'addressLine2',
        'addressline3': 'addressLine3',
        'postalcode': 'postalCode',
    }
    if isinstance(data, dict):
        dictionary = data.copy()
        dict_keys = list(dictionary.keys())
        for key in dict_keys:
            if key in name_cleanse_dict.keys():
                dictionary[name_cleanse_dict[key]] = dictionary.pop(key)
                key = name_cleanse_dict[key]
        return dictionary
    return data

Lets say my dictionary looks like this

person_data = {
    'id': 5,
    'firstname': 'Bob',
    'lastname': 'Woolmer',
    'gender': 'Male',
    'country': 'USA'
    'emailid': 'abs@gmail.com'
}

I am getting the following output:

{
 'gender': 'Male',
 'country': 'USA',
 'ID': 5,
 'firstName': 'Bob',
 'lastName': 'Woolmer',
 'emailId': 'abs@gmail.com'
}

The output I want is:

{
 'ID': 5,
 'firstName': 'Bob',
 'lastName': 'Woolmer',
 'gender': 'Male',
 'country': 'USA',
 'emailId': 'abs@gmail.com'
}

Is there a way to maintain a sequence in case I am replicating this for a dynamic dictionaries.

  • Possible duplicate of [How can I sort a dictionary by key?](https://stackoverflow.com/questions/9001509/how-can-i-sort-a-dictionary-by-key) – DjaouadNM Jun 07 '19 at 21:49
  • 4
    Python dictionaries are, in general, not ordered because the values are accessed by keys, not by indexes. Why would you want to maintain the positions? – DYZ Jun 07 '19 at 21:50
  • I dont want to sort a dictionary by key. I want to maintian the key order even if the first key starts with a 'Z' – Arpit Acharya Jun 07 '19 at 21:51
  • in python 3.6+ dictionary keeps the insertion order – sun_dare Jun 07 '19 at 21:52
  • @ArpitAcharya Check the accepted answer, you can't maintain the order in a dictionary, if you want to maintain the order you can use an `OrderedDict`. – DjaouadNM Jun 07 '19 at 21:53
  • @DYZ: Thats how the responses get passed out as jsons and are used by Analysts who want the IDs at the top followed by Name. Nothing programmatic but more for business users and testers in case we are dealing with dictionaries with a hundred keys – Arpit Acharya Jun 07 '19 at 21:53
  • 3
    For most released versions of Python, there's no such thing as "position" for dictionary entries at all. Dictionaries don't store positions; the positions are just an incidental/coincidental artifact of keys' hash ordering, and since the hash is an indirect derivative of the key itself, there's no high-level control of it (and attempts to force that control would potentially make the storage much less efficient). – Charles Duffy Jun 07 '19 at 21:57
  • 3.6 *does* store position, and pays an extra memory-use cost for doing so, but it pays that cost out of big improvements in dictionary efficiency made over older versions, which is why it doesn't *look* slower or more memory-hungry than older releases. On the other hand, it's slower and more-RAM-hungry than an alternate-universe Python 3.6 that had the same optimizations but *didn't* decide to spend part of its gains on new functionality. – Charles Duffy Jun 07 '19 at 22:00
  • @CharlesDuffy I wouldn't be so sure about that. Insertion-ordering is a side effect of the new memory optimisations in Python 3.6. It does keep an extra array, but thanks to that the hastable can waste as much as *24 times* less memory on buffer space. – Norrius Jun 07 '19 at 22:09
  • @Charles Duffy: This thread says CPython actually improves the memory usage by choosing an implementation that maintains the insertion order https://stackoverflow.com/questions/39980323/are-dictionaries-ordered-in-python-3-6/39980744 – GZ0 Jun 07 '19 at 22:11
  • 1
    @ArpitAcharya If you are not using python-3.6 or newer, even without doing anything to the keys, if you simply read a dictionary from a JSON input using `json` package, the order wouldn't be the same. In that case, the tag should be changed to ```python-3.6```. – justhalf Jun 07 '19 at 22:11

3 Answers3

1

If you can change the original dictionaries to OrderedDicts something like this would work:

from collections import OrderedDict

def clense_data(data):
  name_cleanse_dict = {
    'id': 'ID',
    'emailid': 'emailId',
    'firstname': 'firstName',
    'middlename': 'middleName',
    'lastname': 'lastName',
    'addressline1': 'addressLine1',
    'addressline2': 'addressLine2',
    'addressline3': 'addressLine3',
    'postalcode': 'postalCode',
  }
  if isinstance(data, dict):
    return OrderedDict([(name_cleanse_dict[k], v) if k in name_cleanse_dict else (k, v) for k, v in data.items()])
  return data

def main():
  person_data = OrderedDict([('id', 5),
                             ('firstname', 'Bob'),
                             ('lastname', 'Woolmer'),
                             ('gender', 'Male'),
                             ('country', 'USA'),
                             ('emailid', 'abs@gmail.com')])
  print(person_data)
  new_person_data = clense_data(person_data)
  print(new_person_data)

if __name__ == '__main__':
  main()

Output:

OrderedDict([('id', 5), ('firstname', 'Bob'), ('lastname', 'Woolmer'), ('gender', 'Male'), ('country', 'USA'), ('emailid', 'abs@gmail.com')])
OrderedDict([('ID', 5), ('firstName', 'Bob'), ('lastName', 'Woolmer'), ('gender', 'Male'), ('country', 'USA'), ('emailId', 'abs@gmail.com')])
Sash Sinha
  • 18,743
  • 3
  • 23
  • 40
0

Save the original keys:

order = d.keys()

Modify the keys. Rebuild the dictionary in the original order:

d = {k: d[k] for k in order}

This solution works only for Python 3.6+.

DYZ
  • 55,249
  • 10
  • 64
  • 93
0

You can use a dict comprehension, and dictionary get method with a default value.

{name_cleanse_dict.get(key,key):value for (key,value) in person_data.items()}

The order is guaranteed with Python3.6+, otherwise you should use OrderedDict

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Gelineau
  • 2,031
  • 4
  • 20
  • 30