Python query: list.sort () when a list contains different types of elements

Greetings from the Python world. Day 4 of learning Python 3.3, and I came across the strange property of list.sort .

I created a list of five elements: four lines, the number of which is in the middle. Trying to get list.sort to work gave the expected error due to mix types:

 >>> list = ['b', 'a', 3, 'd', 'c'] >>> list.sort() Traceback (innermost last): File "<stdin>", line 1, in <module> TypeError: unorderable types: int() < str() >>> list ['b', 'a', 3, 'd', 'c'] 

The list does not change.

But then I moved the number to the end, used list.sort again and got the following:

 >>> list = ['b', 'a', 'd', 'c', 3] >>> list.sort() Traceback (innermost last): File "<stdin>", line 1, in <module> TypeError: unorderable types: int() < str() >>> list ['a', 'b', 'c', 'd', 3] 

OK, error. But the list was sorted, bringing the number to the end. I could not find any explanation for this on this site or in Langtangen. Is there any underlying reason for this behavior? Would it be helpful in some situation?

+8
python sorting list
source share
5 answers

From Python 3 docs :

This method sorts the list in place using only <comparisons between Items. Exceptions are not suppressed - if any comparison operations fail, the entire sort operation fails (and the list is likely to be on the left in a partially changed state).

Documents do not guarantee any behavior in particular, but items will most likely be left in partial sorting. The sort order in which they were located when the exception occurred, and this order may vary depending on the implementation or, possibly (but unlikely) two subsequent program runs.

If you want to try sorting items without worrying about unsuccessful reordering, you can use the built-in sorted function, which will return a new list and not change the original.

 >>> seq = ['b', 'a', 3, 'd', 'c'] >>> try: ... seq = sorted(seq) # if sorted fails, result won't be assigned ... except Exception: # you may only want TypeError ... pass ... >>> seq ['b', 'a', 3, 'd', 'c'] # list unmodified 

EDIT: reach out to everyone by saying something like

when he sees two different types, an exception occurs

I know that you probably know that such an expression is a simplification, but I think that not clarity, it will cause confusion.

The following example consists of two classes A and B that support comparison with each other through their respective __lt__ methods. It displays a list mixed from these two types, sorted by list.sort() , and then printed in sorted order without any exceptions:

 class A: def __init__(self, value): self.a = value def __lt__(self, other): if isinstance(other, B): return self.a < other.b else: return self.a < other.a def __repr__(self): return repr(self.a) class B: def __init__(self, value): self.b = value def __lt__(self, other): if isinstance(other, A): return self.b < other.a else: return self.b < other.b def __repr__(self): return repr(self.b) seq = [A(10), B(2), A(8), B(16), B(9)] seq.sort() print(seq) 

The result of this:

 [2, 8, 9, 10, 16] 

It doesn’t matter that you understand every detail of this. This is just to illustrate that a list of mixed types can work with list.sort() if all parts are there.

+9
source share

This is nothing unusual. Just sort() does not check if the list contains consistent data types, but tries to sort it. So, as soon as your element is at the end, it has been analyzed lately, so the algorithm sorted part of the list before it found an error.

And no - this is not useful, since it depends heavily on the sorting mechanism implemented.

+2
source share

depends on how the data needs to be sorted, but something like this might work

 l = ['a',3,4,'b'] sorted([str(x) for x in l]) ['3', '4', 'a', 'b'] 
+2
source share

I write below, believing that I know the data types in the list, can be inefficient. My idea is to split this list into sub-lists based on the data type, then sort each individual list and combine.

 input= ['b', 'a', 3, 'd', 'c'] strs = list(filter(lambda x : type(x) ==str,input)) ints = list(filter(lambda x: type(x) == int, input)) output = sorted(strs) + sorted(ints) 
+1
source share

If in your Dictionary you have mixed and different data types, such as Int and Str; You can use this option:

 **key_a.sort(key=str)** 

and sample function: >>>

def my_dic (a): key_a.sort (key = str) return key_a

0
source share

All Articles