45

I tried to maintain the order of a Python dictionary, since native dict doesn't have any order to it. Many answers in SE suggested using OrderedDict.

from collections import OrderedDict

domain1 = { "de": "Germany", "sk": "Slovakia", "hu": "Hungary",
    "us": "United States", "no": "Norway"  }

domain2 = OrderedDict({ "de": "Germany", "sk": "Slovakia", "hu": "Hungary",
    "us": "United States", "no": "Norway"  })

print domain1
print " "    
for key,value in domain1.iteritems():
    print (key,value)

print " "

print domain2
print ""
for key,value in domain2.iteritems():
    print (key,value)

After iteration, I need the dictionary to maintain its original order and print the key and values as original:

{
    "de": "Germany",
    "sk": "Slovakia",
    "hu": "Hungary",
    "us": "United States",
    "no": "Norway"
}

Either way I used doesn't preserve this order, though.

Arya McCarthy
  • 8,554
  • 4
  • 34
  • 56
Eka
  • 14,170
  • 38
  • 128
  • 212
  • 2
    You're constructing an ordinary `dict` first (because `{ ... }` literals are ordinary `dict` objects) and then passing that into the `OrderedDict` constructor, which no longer sees your explicit order. You need to add items into the `OrderedDict` directly. – Daniel Pryden Jul 15 '17 at 05:54
  • Question has been answered in https://stackoverflow.com/questions/41866911/ordereddict-isnt-ordered – ilias iliadis Dec 06 '17 at 02:25

4 Answers4

72

You need to pass it a sequence of items or insert items in order - that's how it knows the order. Try something like this:

from collections import OrderedDict

domain = OrderedDict([('de', 'Germany'),
                      ('sk', 'Slovakia'),
                      ('hu', 'Hungary'),
                      ('us', 'United States'),
                      ('no', 'Norway')])

The array has an order, so the OrderedDict will know the order you intend.

Mark
  • 90,562
  • 7
  • 108
  • 148
  • 4
    A pedantic note: an iterable is not sufficient (dictionaries and sets are iterable after all). You need to pass it something closer to a sequence. – Jared Goguen Jul 15 '17 at 14:29
4

In the OrderedDict case, you are creating an intermediate, regular (and hence unordered) dictionary before it gets passed to the constructor. In order to keep the order, you will either have to pass something with order to the constructor (e.g. a list of tuples) or add the keys one-by-one in the order you want (perhaps in a loop).

Jared Goguen
  • 8,772
  • 2
  • 18
  • 36
3

Late answer, but here's a python 3.6+ oneliner to sort dictionaries by key without using imports:

d = { "de": "Germany", "sk": "Slovakia", "hu": "Hungary",
    "us": "United States", "no": "Norway"  }
d_sorted = {k: v for k, v in sorted(d.items(), key=lambda x: x[1])}
print(d_sorted)

Output:

{'de': 'Germany', 'hu': 'Hungary', 'no': 'Norway', 'sk': 'Slovakia', 'us': 'United States'}

Python Demo

Pedro Lobito
  • 94,083
  • 31
  • 258
  • 268
2

You can use OrderedDict but you have to take in consideration that OrderedDict will not work outside of your running code.

This means that exporting the object to JSON will lose all the effects of OrderedDict.

What you can do is create a metadata array in which you can store the keys "de", sk", etc. in an ordered fashion. By browsing the array in order you can refer to the dictionary properly, and the order in array will survive any export in JSON, YAML, etc.

Current JSON:

{ "de": "Germany", "sk": "Slovakia", "hu": "Hungary", "us": "United States", "no": "Norway"  }

New object countries:

countries = {
  "names" : { 
    "de": "Germany", "sk": "Slovakia", "hu": "Hungary", "us": "United States", "no": "Norway"  
  },
  "order" : [ 
    "de", "sk", "hu", "us", "no" 
  ]
}

Code that will print the long names in order:

for code in countries['order']:
 print(countries['names'][code])
Fabien
  • 4,862
  • 2
  • 19
  • 33
  • Actually, you can load an OrderedDict using json.load(). There is a second parameter which tells the load method to create an OrderedDict object to keep order the same. https://stackoverflow.com/questions/6921699/can-i-get-json-to-load-into-an-ordereddict – justdan23 Jun 02 '22 at 13:15