Home > other >  Sorting python tuples contain non-comparable elements
Sorting python tuples contain non-comparable elements

Time:10-15

When trying to compare dictionaries, python raises a TypeError:

{"a" : "b"} < {"a" : "b"} # TypeError

When trying to compare tuples, python does it elementwise:

(1, 2) > (1, 1) # True

Therefore, I expected that comparing tuples containing dictionaries would result in a TypeError if the elements preceding the dictionaries were equal because it would then be forced to compare the dictionaries, which would raise a TypeError. This is not the case:

(3, {"a" : "b"}) < (3, {"a" : "b"}) # False, no TypeError

I've read through the documentation I could find regarding Python sorting and did not see anything documenting this behavior. Can I rely on this behavior staying the same in future versions?

CodePudding user response:

This is explained in the docs:

Lexicographical comparison between built-in collections works as follows:

For two collections to compare equal, they must be of the same type, have the same length, and each pair of corresponding elements must compare equal (for example, [1,2] == (1,2) is false because the type is not the same).

Collections that support order comparison are ordered the same as their first unequal elements (for example, [1,2,x] <= [1,2,y] has the same value as x <= y). If a corresponding element does not exist, the shorter collection is ordered first (for example, [1,2] < [1,2,3] is true).

So the first thing that the tuple comparison will do is to find the unequal elements, as there are not unequal elements in your tuple the result is False, and there is no need to call the code for <.

This is further confirmed by looking at the implementation of the comparison of tuples:

for (i = 0; i < vlen && i < wlen; i  ) {
    int k = PyObject_RichCompareBool(vt->ob_item[i],
                                     wt->ob_item[i], Py_EQ);
    if (k < 0)
        return NULL;
    if (!k)
        break;
}

if (i >= vlen || i >= wlen) {
    /* No more items to compare -- compare sizes */
    Py_RETURN_RICHCOMPARE(vlen, wlen, op);
}

The for loop in the code above tries to find the first unequal elements and if not found delegates the comparison to the size of the tuples.

  • Related