1

Given this simplified example to sort:

l = [10, '0foo', 2.5, 'foo', 'bar']

I want to sort l so that numeric is always before strings. In this case, I'd like to get [2.5, 10, '0foo', 'foo', 'bar']. Is it possible make numeric and string temporarily comparable (with strings always larger than numeric)?

Note it is not easy to provide a key function to sorted if you are thinking about it. For example, converting numeric to string won't work because "10" < "2.5".

3

1 Answer 1

1

A way that you might do this does involve passing a key to sorted. it looks like this:

sorted(l, key=lambda x:(isinstance(x str), x))

This works because the key returns a tuple with the type of x and its value. Because of the way tuples are compared. Items at index 0 are compared first and if it they are the same, then next two items are compared and so on if they also are the same. This allows for the values to be sorted by type (string or not a string), then value if they are a similar type.

A more robust solution that also can handle further types might use a dictionary in the key function like this:

 sorted(l,key=lambda x:({int:0, float:0, str:1, list:2, set:3}[type(x)], x))

further types can be added as necessary.

Sign up to request clarification or add additional context in comments.

4 Comments

it is a good idea. but the solution does not work yet. it makes the comparison between float and int problematic. For example, 1 would be ordered larger than 2.5 with your solution, because <class int> is ordered after <class float>.
@RNA I believe that it should work correctly with this slight modification.
It is not generic, though. I have to specify all the types. But your solution points to the right direction
@RNA if the only types you are sorting that are not numerical are strings, that the first piece of code should work.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.