Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a set of numbers appear to be sorted? [duplicate]

Running this code multiple times

t = {'a', 'b', 'c', 'd'}
print(t)

could print something like:

{'c', 'b', 'a', 'd'} 
{'d', 'b', 'c', 'a'} # different
{'d', 'b', 'c', 'a'} # same
{'a', 'd', 'b', 'c'} # different
{'a', 'b', 'c', 'd'} # different
# etc

(If you are using the console to replicate it, make sure you click Rerun every time before you re-paste the code and execute it. If you still can't replicate, perhaps you have hash randomization not equal to random. On Python 3.3 and greater, hash randomization is turned on by default.)


On the other hand, the code below always prints the same set, and it's actually sorted:

s = {1, 6, 3.3, 4}
print(s) 

# prints: 
# {1, 3.3, 4, 6}
# {1, 3.3, 4, 6}
# {1, 3.3, 4, 6}
# {1, 3.3, 4, 6}

Question:
Why do sets of numbers appear to be always sorted and are they really always sorted?

like image 508
user Avatar asked Sep 09 '15 16:09

user


People also ask

Can a sorted array have duplicates?

In sorted array, all duplicate elements will be placed adjacent to each other. So, we can easily track unique elements and place them into front positions of array. For this purpose, we use one fast pointer to scan array and slow pointer to track the position of unique elements.


1 Answers

Note, I don't have python3.4 handy, but on python2.7 this isn't always the case (and I'd expect that to be true of python3.4 too).

I can even change the order of the elements based on how I put them into the set:

>>> print({1, 9})
set([9, 1])
>>> print({9, 1})
set([1, 9])
>>> set([9, 1])
set([9, 1])
>>> set([1, 9])
set([1, 9])

The order is determined by the hash of the element and by when it was inserted (in the case of hash collisions). In CPython, integers hash to themselves and a dict/set has 8 slots free to start with. Since there are 8 spots available, we can hash numbers 0 -> 7 (inclusive) without a hash collision. However, if we try to hash 8 and 0 (or 9 and 1) in the same set, we'll get a collision. if 9 is already in the set and then we try to put 1 in, python looks and says "Oh snap, that slot's taken -- Now I need to put it in the next most favorable slot". The details of collision resolution are beyond what I've looked into, so I can't offer insight into what slot that is ...

Note if we had more than ~5 elements in the set, then it would be resized (IIRC, to 16, then 32, then 64, ...) which changes which elements would collide (naturally).

like image 168
mgilson Avatar answered Nov 10 '22 18:11

mgilson