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".

RNA
  • 146,987
  • 15
  • 52
  • 70

1 Answers1

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.

micsthepick
  • 562
  • 7
  • 23
  • 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 `` is ordered after ``. – RNA Mar 15 '17 at 21:11
  • @RNA I believe that it should work correctly with this slight modification. – micsthepick Mar 15 '17 at 22:10
  • It is not generic, though. I have to specify all the types. But your solution points to the right direction – RNA Mar 16 '17 at 00:14
  • @RNA if the only types you are sorting that are not numerical are strings, that the first piece of code should work. – micsthepick Mar 16 '17 at 01:11