python: Difference between operation sorted(set(array)) vs set(sorted(array))

Viewed 100

I was solving a question on Hacker rank when I came across a strange behavior.

Lists generated from following 2 pieces of code should be same.

#array is list containing random elements
#method 1
array1 = list(set(sorted(array)))

#method 2
array2 = sorted(set(array))

#Hence following line of code should return True
array1 == array2

However, depending on the size of the list the answer is different. If the size of list if small, lets say 10 elements then that line of code returns True. However, if the list is sufficiently long that statement returns False.

I wanted to understand what is going on behind the scenes as logically in both the cases the answer should be True.

Examples 1:

In [60]: array                                                                                                                                                                                 
Out[60]: [9, 8, 5, 0, 2, 6, 7, 5, 1, 3]

In [61]: sorted(set(array)) == list(set(sorted(array)))                                                                                                                                        
Out[61]: True

Example 2:

In [103]: import requests                                                                                                                                                                      

In [104]: link = "https://hr-testcases-us-east-1.s3.amazonaws.com/70945/input02.txt?AWSAccessKeyId=AKIAJ4WZFDFQTZRGO3QA&Expires=1591229125&Signature=ocC7OZJJVIxAI00bzLNu73T%2BZTk%3D&response-
     ...: content-type=text%2Fplain"                                                                                                                                                           

In [105]: ipstring = requests.get(link).content.decode("utf-8")                                                                                                                                

In [106]: a = list(map(int, ipstring.split("\n")[2].split()))                                                                                                                                  

In [107]: sorted(set(a)) == list(set(sorted(a)))                                                                                                                                               
Out[107]: False
1 Answers

No, logically, it shouldn't be True.

sorted(set(a)) == list(set(sorted(a)))

On the right-hand side, you sort your list, then you call set on it, which loses the order, you then create a list out of it, which gives you some arbitrary order, whereas sorted(set(a)) will always be sorted...

For the small examples, it just happens to be the case that set preserved the order, that's because smaller, positive integers just hash to themselves.

So consider:

>>> data = [9, 8, 5, 0, 2, 6, 7, 5, 1, 3]
>>> data.sort()
>>> data
[0, 1, 2, 3, 5, 5, 6, 7, 8, 9]
>>> list(map(hash, data))
[0, 1, 2, 3, 5, 5, 6, 7, 8, 9]

But that is an implementation detail...

Related