I am trying to solve a problem of sorting angles in the range of 0 to Pi radians and Pi to -Pi to 0 radians as one continuous range. I know this might be difficult to understand. Let me quote an example below.
The following are examples of the final range I would like to get after sorting a list of jumbled angles:
Example Inputs
Case - 1: Pi/4, 0, Pi/2, -Pi/20, Pi, -Pi/4, -Pi, -3*Pi/4, 3*Pi/4, -Pi/2, -Pi/10
Case - 2: -Pi/20, Pi/2, Pi, -Pi/2, -Pi/10, -Pi/4, Pi/4, 0,-Pi, -3*Pi/4, 3*Pi/4
Expected Output
0, Pi/4, Pi/2, 3*Pi/4, Pi, -Pi, -3*Pi/4, -Pi/2, -Pi/4, -Pi/10, -Pi/20
As you can see in the above list (Expected Output), the sorted list basically represents a continuous range of angles in a circle (starting from 0, making a full 360 degree rotation and ending at 0).
It is easy to sort these numbers if they are simply in a range of 0 to 360. But it gets trickier when the range is split into positive and negative angles like this.
Extra Info: For some kind of strange performance reasons, I am not allowed to do the conversion of this angle into the range 0 to 2Pi for sorting. The range has to be preserved while sorting. My first solution was to convert it into 2pi range using (theta 2pi) % (2*pi). But that solution got rejected. So I am now stuck trying to figure out how can I sort this without converting it into a different range
CodePudding user response:
Create a custom compare function and pass it to sort
/sorted
using functools.cmp_to_key
:
def angle_compare(a, b):
def cmp(a, b):
return (a > b) - (b > a)
if (a < 0) == (b < 0): # both positive or both negative
return cmp(a, b)
return cmp(b, a)
>>> Pi = 3.14
>>> l1 = [Pi/4, 0, Pi/2, -Pi/20, Pi, -Pi/4, -Pi, -3*Pi/4, 3*Pi/4, -Pi/2, -Pi/10]
>>> sorted(l1, key=functools.cmp_to_key(angle_compare))
[0, 0.785, 1.57, 2.355, 3.14, -3.14, -2.355, -1.57, -0.785, -0.314, -0.157]