I was working on a geometry project in python and I came across an intriguing problem. Assume I have a list of Cartesian coordinates like this:
[[1, 0], [3, 0], [2, 1], [3.5, 2], [4, 3], [6, 1], [6.5, 0], [10, 2], [10, 5], [9, 3.5], [7, 3], [9, 7], [7, 8], [5, 7], [4, 5], [2, 8], [1, 7], [0, 5], [1, 3], [0, 2]]
What would be the best way to sort this list by descending y-value THEN increasing x-value if two coordinates exist with the same y-value? The output should be:
[[2, 8], [7, 8], [1, 7], [5, 7], [9, 7], [0, 5], [4, 5], [10, 5], [9, 3.5], [1, 3], [4, 3], [7, 3], [0, 2], [3.5, 2], [10, 2], [2, 1], [6, 1], [1, 0], [3, 0], [6.5, 0]]
You can supply a key function to list.sort
to determine what value each item in your list should be mapped to for sorting. In your case, you can use a tuple of the negative Y-coordinate, and the X-coordinate to get your desired result:
>>> coordinates = [[1, 0], [3, 0], [2, 1], [3.5, 2], [4, 3], [6, 1], [6.5, 0], [10, 2], [10, 5], [9, 3.5], [7, 3], [9, 7], [7, 8], [5, 7], [4, 5], [2, 8], [1, 7], [0, 5], [1, 3], [0, 2]]
>>> coordinates.sort(key=lambda x: (-x[1], x[0]))
>>> coordinates
[[2, 8], [7, 8], [1, 7], [5, 7], [9, 7], [0, 5], [4, 5], [10, 5], [9, 3.5], [1, 3], [4, 3], [7, 3], [0, 2], [3.5, 2], [10, 2], [2, 1], [6, 1], [1, 0], [3, 0], [6.5, 0]]
Poke's answer is the right answer in most cases.
Just in case you are doing this on Python prior to Python 2.4 or if the comparison function is really expensive, you can use Decorate-Sort-Undecorate (DSU or the Schwartzian transform )
>>> coord = [[1, 0], [3, 0], [2, 1], [3.5, 2], [4, 3], [6, 1], [6.5, 0], [10, 2], [10, 5], [
9, 3.5], [7, 3], [9, 7], [7, 8], [5, 7], [4, 5], [2, 8], [1, 7], [0, 5], [1, 3], [0, 2]]
>>> decorated=[[(-y,x),x,y] for x,y in coord]
>>> [[x,y] for t,x,y in sorted(decorated)]
[[2, 8], [7, 8], [1, 7], [5, 7], [9, 7], [0, 5], [4, 5], [10, 5], [9, 3.5], [1, 3], [4, 3], [7, 3], [0, 2], [3.5, 2], [10, 2], [2, 1], [6, 1], [1, 0], [3, 0], [6.5, 0]]
Or:
>>> [[x,y] for t,x,y in sorted([[(-y,x),x,y] for x,y in coord])]
[[2, 8], [7, 8], [1, 7], [5, 7], [9, 7], [0, 5], [4, 5], [10, 5], [9, 3.5], [1, 3], [4, 3], [7, 3], [0, 2], [3.5, 2], [10, 2], [2, 1], [6, 1], [1, 0], [3, 0], [6.5, 0]]
These techniques (and more) are in the Python sorting HowTo
Using sorted
and specifying the sorting criterion with a lambda
function using a tuple:
>>> coord = [[1, 0], [3, 0], [2, 1], [3.5, 2], [4, 3], [6, 1], [6.5, 0], [10, 2], [10, 5], [9, 3.5], [7, 3], [9, 7], [7, 8], [5, 7], [4, 5], [2, 8], [1, 7], [0, 5], [1, 3], [0, 2]]
>>> sorted(coord, key=lambda x: (-x[1], x[0]))
[[2, 8], [7, 8], [1, 7], [5, 7], [9, 7], [0, 5], [4, 5], [10, 5], [9, 3.5], [1, 3], [4, 3], [7, 3], [0, 2], [3.5, 2], [10, 2], [2, 1], [6, 1], [1, 0], [3, 0], [6.5, 0]]
The order in the lambda function tuple defines the order by which the criterion are considered.
x[1] : sort by second element in ascending order
-x[1] : sort by second element in descending order
x[0] : sort by first element in ascending order
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.