0

I have a dictionary:

dict_a = dict(zip(('a','b','c','d','e'),(1,2,3,4,5)))

The output is:

dict_a = {'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}

I want to know why it is not:

dict_a = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

I do know dict_a is a not sorted object, but still want to know why the key order is a, c, b, e, d, not in the other orders.

Thanks

Ben
  • 946
  • 1
  • 11
  • 19
  • it has to do with how the keys are hashed and how they are retrieved, you'd have to look into python source code to find any more of an explanation. – R Nar Nov 27 '15 at 00:49
  • This is going to be implementation dependent, and you haven't told us what version of Python you're using. CPython? Pypy? Jython? – jme Nov 27 '15 at 00:50
  • @jme I am using python2.7 – Ben Nov 27 '15 at 00:52
  • Look [here](http://stackoverflow.com/questions/327311/how-are-pythons-built-in-dictionaries-implemented) if you're interested in the nitty-gritty details of how `dict` is implemented. But the reason you see things in this order is likely due to the fact that `hash('a') < hash('c') < hash('b') < hash('e') ...`, for whatever reason. If you're interested in the technicalities, feel free to dive in. But as a user of the language, the order of the dict keys is simply an implementation detail that you should never, ever rely on. – jme Nov 27 '15 at 00:58

6 Answers6

2

Dictionaries are not just sorted, they are unordered. Dictionaries are, in the deeper level, keys pointing to memory addresses.

Let's tackle this another way. In traditional languages you have arrays. Internally, arrays are contiguous memory, i.e. x[0] and x[1] are next to eachother in memory. Dictionaries meanwhile are loose collections of pointers. y[a] and y[b] have no physical relationship they have no order.

Dylan Lawrence
  • 1,503
  • 10
  • 32
  • "Dictionaries, by their very definition, can never be ordered" Tell that to an `OrderedDict` ;). I'm assuming you meant something like "Python dictionaries, by definition, have arbitrary order". But there's nothing about hash tables which means that they cannot (or do not) have an order. – jme Nov 27 '15 at 00:52
  • @jme Well... yes technically, but a traditional, i.e. progenitor dictionary, is unorderable. I'll revise though. – Dylan Lawrence Nov 27 '15 at 00:53
  • 1
    'not just *un*sorted'? – Matt Hall Nov 27 '15 at 00:54
  • @kwinkunks well fundamentally sorting a dictionary requires auxiliary structure, I removed the statement however to avoid confusion. – Dylan Lawrence Nov 27 '15 at 00:54
  • So why it has to be a, c, b, e, d. I got such sequence everytime. – Ben Nov 27 '15 at 00:55
  • @Ben it has to do with how python is doing things internally, the order is arbitrary, but consistent. Fundamentally we can't call it ordered, but it comes out that way due to how python internally handles dictionaries. – Dylan Lawrence Nov 27 '15 at 00:56
1

As you said, dictionaries are not ordered objects. So no matter what order you add items to it they will be jumbled up. Dictionary do not support indexing, so therefore it has no reason to be in the correct order. I guess it saves memory not having to know what position the items are supposed to be.

In a way you can say they have indexing using keys to obtain the associated value and not position as in lists. You can only have a distinct key point to a value as you can only have 1 value at position 0 in a list.

More info at Python documentation

Steven Summers
  • 5,079
  • 2
  • 20
  • 31
1

See longer discussions earlier:

Why is python ordering my dictionary like so?

Why is the order in dictionaries and sets arbitrary?

(And this should rather have been a comment, but I don't have the reputation to write one...)

Community
  • 1
  • 1
pascal
  • 456
  • 4
  • 12
0

Because the regular dictionay does not contains insertion order process. It use arbitrary order. So if you want to use a dictionary as ordered you should use OrderedDict, and it contains insertion order process. But you need to consider your sutition when you use ordered dictionary, because it slower then regular dictionary when you insert item and update it.

RockOnGom
  • 3,893
  • 6
  • 35
  • 53
0

If you want to maintain the order of the items in your dictionary, you can use an OrderedDict:

from collections import OrderedDict
dict_a = ()
dict_a['a'] = 1
dict_a['b'] = 2
dict_a['c'] = 3
dict_a['d'] = 4
dict_a['e'] = 5

Then the order of the dictionary will be maintained:

dict_a = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)])
  • Thx. I know how to add order to it. The question is: why this dict has to be a, c, b, e, d – Ben Nov 27 '15 at 01:17
  • I think it's somewhat random how the ordering works, in the way that Python implements the `dict` as a hash table. Creating the `dict` in the same way a second time, or on a different computer, might return a different order than a, c, b, e, d. –  Nov 27 '15 at 01:23
  • In fact, on my computer, I get `{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}` –  Nov 27 '15 at 01:25
  • what computer and os did you use? :) – Ben Nov 27 '15 at 01:30
  • Mac OS X Mavericks on a MacBook Air, running Python 2.7.10 from Macports –  Nov 27 '15 at 01:31
0

So, first I thought it was zip that was causing it. However it is not zip since when I enter

>>zip(('a','b','c','d','e'),(1,2,3,4,5)

The output is from left to right

[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]

So I considered maybe it has to do with memory storage between our systems (I'm using windows10). I checked with the same input and got the same output

>>dict_a = dict(zip(('a','b','c','d','e'),(1,2,3,4,5)))

{'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}

Now, I checked the documentation at python built-in types. Their code is more what you'd expect where

>>c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))

has the output from right to left, (which I'm guessing after zipping the two lists the dictionary adds from popping values and using the update function).

>>{'three': 3, 'two': 2, 'one': 1}

No matter how you put in the different dictionaries it still has the same output (dictionaries like sets as OP states order does not matter).

>>d = dict([('two', 2), ('one', 1), ('three', 3)])
{'three': 3, 'two': 2, 'one': 1}

The python manual states for built in types

If keyword arguments are given, the keyword arguments and their values are added to the dictionary created from the positional argument

Given that the key arugments don't change even with or without changing zip I tried one last thing. I decided to switch the keys and items

>>d = dict([(1,'a'), (2,'b'),(3,'c'),(4,'d'),(5,'e')])

Which outputted what we expected

{1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}

Ordered by numbers. My only explanation is that during the actual compiling the letters 'a','b','c','d','e' are being stored as another form (e.g. hexadecimal not ascii) which would change the order of a,b,c,d,e in the list that is used for keys in the dictionary.

user2723240
  • 803
  • 1
  • 13
  • 23