Reputation: 67
I have a list of class objects my_rectangle:
class my_rectangle:
def __init__(self,text,x_start,y_start,x_end,y_end):
self.text=text
self.x_start=x_start
self.y_start=y_start
self.x_end=x_end
self.y_end=y_end
self.x_centroid=(self.x_start+self.x_end)/2
self.y_centroid=(self.y_start+self.y_end)/2
Using the class attributes (x_centroid
and y_centroid
) which give the coordinates of the centroid, I wanted to order this list, using as an order left-to-right then top-to-bottom (normal English reading order)?
Say I have:
A=my_rectangle('Hi,',1,3,2,4)
B=my_rectangle('Im',3,3,3,4)
C=my_rectangle('New',1,1,2,2)
my_list=[C,B,A]
And I want to order it to get:
my_sorted_list=[A,B,C]
Which is a representation of the text:
""" Hi, I'm
New
"""
Upvotes: 2
Views: 5214
Reputation: 23064
You can make custom classes sortable by defining a __lt__
method. This takes care of the <
operator which is used in default sorting.
class Rectangle:
def __init__(self,text,x_start,y_start,x_end,y_end):
self.text=text
self.x_start=x_start
self.y_start=y_start
self.x_end=x_end
self.y_end=y_end
@property
def centroid(self):
return (self.x_start+self.x_end)/2, (self.y_start+self.y_end)/2
def __lt__(self, other):
"""Using "reading order" in a coordinate system where 0,0 is bottom left"""
try:
x0, y0 = self.centroid
x1, y1 = other.centroid
return (-y0, x0) < (-y1, x1)
except AttributeError:
return NotImplemented
def __repr__(self):
return 'Rectangle: ' + self.text
I'm defining centroid
as a property, so that it will update if you change any of the other coordinates after initializing a Rectangle.
You will get this output if you use the data from your question.
>>> rectangles = [
... Rectangle('A',1,3,2,4),
... Rectangle('B',3,3,3,4),
... Rectangle('C',1,1,2,2),
... ]
>>> print(sorted(rectangles))
[Rectangle: A, Rectangle: B, Rectangle: C]
Upvotes: 3
Reputation: 168626
Generating a sorted list is the specialty of the builtin function sorted()
.
Sorting using multiple values can be accomplished by providing a key
function, which key function returns the values as a tuple. The resulting list is then sorted according to the lexicographical ordering of the tuple.
#UNTESTED
my_sorted_list = sorted(my_list, key=lambda item: (item.x_centroid, item.y_centroid))
Upvotes: 4