Python dictionary returns keys in random order

Viewed 103

I have a simple dict of dicts as follows:

stb = {
    'TH0':{0:'S0',1:'Sample1',2:'Sample2',3:'Sample4'},
    'TH1':{0:'Sa0',1:'Sample1',2:'Sample2',3:'Sample4'},
    'TH2':{0:'Sam0',1:'Sampled1.0',2:'Sampled2.0',3:'Sampled4.0'},
    'TH3':{0:'Samp0',1:'Sample1',2:'Sample2',3:'Sample4'},
    'TH4':{0:'Sampl0',1:'Sample1',2:'Sample2',3:'Sample4'},
}
tb = stb

theaders = []
for k in tb.keys():
    theaders.append(k)
columns = len(theaders)
rows = len(tb[theaders[0]])
print(tb[theaders[0]])
print('Cols: ',columns)
print('Rows: ',rows)

for h in theaders:
    print(h)
`

The problem here is that, every single time I run this snippet, theaders has values in a random order.For example, First Run:

{0: 'Samp0', 1: 'Sample1', 2: 'Sample2', 3: 'Sample4'}
Cols:  5
Rows:  4
TH3
TH0
TH4
TH1
TH2

Second Run:

{0: 'S0', 1: 'Sample1', 2: 'Sample2', 3: 'Sample4'}
Cols:  5
Rows:  4
TH0
TH2
TH4
TH1
TH3

Note: This was never the case before but for some reason, it just started happening and I really need those keys in their correct order.

Also Note: Simply sorting this would not work as the real data has string keys that should not be sorted.

2 Answers

For python 3.6, dictionaries maintaining insertion order is an implementation detail. In python 3.7 it's guaranteed and documented. You didn't specify which version of Python you're using but I assume it's earlier than 3.6. One option would be to use an ordered dictionary, OrderedDict from the collections module, where insertion order is guaranteed for older versions of python.

That is because dictionaries are unordered in Python. If you are looking to retain the order of keys, you should try OrderedDict as follows.

from collections import OrderedDict

stb = OrderedDict(
    TH0 = {0:'S0',1:'Sample1',2:'Sample2',3:'Sample4'},
    TH1 = {0:'Sa0',1:'Sample1',2:'Sample2',3:'Sample4'},
    TH2 = {0:'Sam0',1:'Sampled1.0',2:'Sampled2.0',3:'Sampled4.0'},
    TH3 = {0:'Samp0',1:'Sample1',2:'Sample2',3:'Sample4'},
    TH4 = {0:'Sampl0',1:'Sample1',2:'Sample2',3:'Sample4'},
)

tb = stb # As I see, this is not necessary (as we are not using std anywhere in the 
         # following code)

theaders = []
for k in tb.keys():
    theaders.append(k)

columns = len(theaders)
rows = len(tb[theaders[0]])

print(tb[theaders[0]])
print('Cols: ',columns)
print('Rows: ',rows)

for h in theaders:
    print(h)
Related