4

Python sorts lists of tuples by looking at the elements of the tuples, in order. Since sets are unordered, how does Python sort a list of sets?

Edit: The question and accepted answer in this post are more general and the document given is very in-depth. My question is not a duplicate.

Community
  • 1
  • 1
Lupilum
  • 363
  • 2
  • 11
  • 1
    Possible duplicate of [About Python's built in sort() method](http://stackoverflow.com/questions/1517347/about-pythons-built-in-sort-method) – Ari Cooper-Davis Mar 22 '17 at 16:07
  • If you had tried it out you would see that it does not. – Ma0 Mar 22 '17 at 16:08
  • 3
    @Ev.Kounis Depends on the test case. For example, `sorted([{1,2,3,4}, {1,2}, {1}, {1,2,3}])` does give me `[{1}, {1, 2}, {1, 2, 3}, {1, 2, 3, 4}]` as expected. – Stefan Pochmann Mar 22 '17 at 16:12

3 Answers3

8

Regardless of what's in a list, the elements' __lt__ methods are the only comparison methods consulted. For sets, a < b means "a is a proper subset of b", which isn't enough to define a total order. That's why the result is, in general, undefined. It may be any permutation of the original list consistent with which pairs of list elements the implementation happens to apply __lt__ to.

If, for every pair of sets in the list, one is in fact a proper subset of the other, then the list will be sorted from smallest (cardinality) set to largest. Otherwise little can be said. For example:

>>> sorted([{5, 6}, {3, 4}, {5}, {3}])  # nothing changes
[{5, 6}, {3, 4}, {5}, {3}]

What happens is a consequence of undefined implementation details. Since I wrote list.sort(), I know what happens in this case, but it's not guaranteed to always work this way:

First the implementation asks "is {3, 4} < {5, 6}?". No, so the order of the first two elements is consistent with being sorted already. It next asks "is {5} < {3, 4}?". No, so the first three elements appear to be already sorted. Finally it asks "is {3} < {5}?". No again, so the original list's entire order is consistent with being already sorted, and nothing changes.

A future implementation may, e.g., ask "is {5} < {5, 6}?" at some point, and since "yes" decide {5} needs to appear before {5, 6}. So the result is simply not defined.

Tim Peters
  • 67,464
  • 13
  • 126
  • 132
2

Sets are partially ordered, so

the output of the list.sort() method is undefined for lists of sets.

https://docs.python.org/3/library/stdtypes.html#set

Josh Lee
  • 171,072
  • 38
  • 269
  • 275
  • Unless the subset relation happens to be a strict weak order on the particular sets in your list. Then the results are defined. – user2357112 Mar 22 '17 at 16:58
2

The __le__ operator on sets define the partial ordering "subset". Therefore the sorted order is undefined.

{3} < {5} is false, but so is {5} < {3} so the sort algorithm will usually not rearrange them.

Citation from Python3 documentaton about sets:

The subset and equality comparisons do not generalize to a total ordering function. For example, any two nonempty disjoint sets are not equal and are not subsets of each other, so all of the following return False: a<b, a==b, or a>b.

Since sets only define partial ordering (subset relationships), the output of the list.sort() method is undefined for lists of sets.

Community
  • 1
  • 1
Moberg
  • 5,253
  • 4
  • 38
  • 54