Reputation: 1
I have a singly linked list, where the data is a custom object I've created, named 'Patient', and I sort the linked list based on the 'Patient.points'.
however, I want to also sort the list by 'Patient.bmi', as a secondary filter, if the two patients being compared have the same number of points.
the way I want to paitents to be sorted by the BMI filter is to have the patients with the worst bmi top, going in ascending order. I have four 'conditions', 'obese, overweight, underweight and normal'. I want obese, overweight and normal as descending order, and underweight in ascending order.
this is my linked list:
class Node:
def __init__(self):
self.data = None
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def addNode(self, data):
curr = self.head
if curr is None:
n = Node()
n.data = data
self.head = n
return
if curr.data.points == data.points and curr.data.condition == 'underweight':
if curr.data.bmi > data.bmi:
n = Node()
n.data = data
n.next = curr
self.head = n
return
elif curr.data.points == data.points and curr.data.condition != 'underweight':
if curr.data.bmi < data.bmi:
n = Node()
n.data = data
n.next = curr
self.head = n
return
if curr.data.points < data.points:
n = Node()
n.data = data
n.next = curr
self.head = n
return
while curr.next is not None:
if curr.next.data.points < data.points:
break
curr = curr.next
n = Node()
n.data = data
n.next = curr.next
curr.next = n
return
def __str__(self):
data = []
curr = self.head
while curr is not None:
data.append(curr.data)
curr = curr.next
return "[%s]" %(', '.join(str(i) for i in data))
def __repr__(self):
return self.__str__()
and this is the data that gets returned:
Paitent name: BDF237 age: 79 Years 2 Months 14 Days BMI: 37.960398071201396 weight classification: obese
Paitent name: ABE127 age: 20 Years 6 Months 20 Days BMI: 34.54054238911118 weight classification: obese
Paitent name: ABD721 age: 73 Years 4 Months 25 Days BMI: 31.217481789802285 weight classification: obese
Paitent name: DED567 age: 58 Years 5 Months 5 Days BMI: 32.74416118146279 weight classification: obese
Paitent name: DEF444 age: 24 Years 11 Months 25 Days BMI: 31.462672275229988 weight classification: obese
Paitent name: BDF777 age: 93 Years 10 Months 11 Days BMI: 14.705367459122582 weight classification: underweight
Paitent name: BDF098 age: 86 Years 0 Months 13 Days BMI: 13.863739248528747 weight classification: underweight
Paitent name: DDC345 age: 54 Years 3 Months 19 Days BMI: 16.45600644235146 weight classification: underweight
Paitent name: DDD222 age: 73 Years 9 Months 0 Days BMI: 18.166204254194742 weight classification: underweight
Paitent name: DDD555 age: 66 Years 10 Months 0 Days BMI: 17.632653061224488 weight classification: underweight
Paitent name: DEF666 age: 65 Years 10 Months 22 Days BMI: 17.68978885166924 weight classification: underweight
Paitent name: ABE123 age: 69 Years 6 Months 19 Days BMI: 28.010411951109102 weight classification: overweight
Paitent name: ABD111 age: 72 Years 8 Months 0 Days BMI: 26.122448979591837 weight classification: overweight
Paitent name: ABE165 age: 23 Years 3 Months 9 Days BMI: 26.491508201480624 weight classification: overweight
Paitent name: ABE329 age: 82 Years 0 Months 7 Days BMI: 25.46401086464464 weight classification: overweight
Paitent name: DDD124 age: 44 Years 6 Months 27 Days BMI: 27.15271058955713 weight classification: overweight
Paitent name: DED675 age: 45 Years 6 Months 29 Days BMI: 28.735632183908045 weight classification: overweight
Paitent name: DED879 age: 22 Years 9 Months 1 Days BMI: 28.73469387755102 weight classification: overweight
Paitent name: DEF555 age: 27 Years 1 Months 24 Days BMI: 25.847768218818715 weight classification: overweight
Paitent name: ABC234 age: 19 Years 7 Months 19 Days BMI: 23.057725694444446 weight classification: normal
Paitent name: ABD221 age: 50 Years 11 Months 0 Days BMI: 21.872422819032593 weight classification: normal
Paitent name: ABD176 age: 55 Years 11 Months 3 Days BMI: 21.132713440405748 weight classification: normal
Paitent name: ABD231 age: 55 Years 11 Months 29 Days BMI: 20.9572742022715 weight classification: normal
Paitent name: ABD321 age: 59 Years 11 Months 9 Days BMI: 20.429418362441915 weight classification: normal
Paitent name: ABD444 age: 57 Years 5 Months 6 Days BMI: 20.820939916716245 weight classification: normal
Paitent name: ABD401 age: 63 Years 9 Months 22 Days BMI: 21.513858510523864 weight classification: normal
Paitent name: ABD007 age: 22 Years 2 Months 17 Days BMI: 21.62964876033058 weight classification: normal
Paitent name: ABC008 age: 83 Years 1 Months 19 Days BMI: 19.77769866698311 weight classification: normal
Paitent name: ABC101 age: 86 Years 0 Months 13 Days BMI: 18.556773222226116 weight classification: normal
Paitent name: ABC201 age: 26 Years 10 Months 7 Days BMI: 20.303697560696612 weight classification: normal
I believe the issue is in my linked list class in the while class:
while curr.next is not None:
if curr.next.data.points < data.points:
break
However, I'm not sure what I would need to adjust it to, although I do know it needs adjusting
Many thanks in advance!
Upvotes: 0
Views: 62
Reputation: 94
Define __lt__
to compare the conditions in order:
def __lt__(self, other):
if self.Points < other.Points:
return True
elif self.Points == other.Points:
if self.bmi < other.bmi:
return True
else:
return False
else: # self.Points > other.Points
return False
Upvotes: 0
Reputation: 5871
You don't want your linked list to worry about how to compare the patients. Simply override the < operator for the patient class, so that comparing two patients will automatically give the order you want.
Now your linked list class doesn't care about all those fancy rules, because they are handled by the Patient class, as they should be. The linked list just checks
while curr.next is not None:
if curr.next.data < data:
break
The way you do this is you define a function named __lt__ on the Patient class. The letters "lt" are short for "less than" and will be used when you use "<" in your code. Similarly, it will automatically be referenced in a sort.
see also Is it possible to overload the multiple comparison syntax in python?
Here's a quick demo:
import random
class Patient:
def __init__(self, points, bmi):
self.points = points
self.bmi = bmi
def __str__(self):
return '{}, {}'.format(self.points, self.bmi)
def __lt__(self, other):
if self.points < other.points:
return True
if self.bmi < 18.5:
if self.bmi > other.bmi:
return True
else:
if self.bmi < other.bmi:
return True
return False
patients = [
Patient(32, 25),
Patient(32, 24),
Patient(32, 18),
Patient(32, 15),
Patient(20, 25),
Patient(20, 24),
Patient(20, 18),
Patient(20, 15),
]
random.shuffle(patients)
patients.sort()
for patient in patients:
print(patient)
20, 18
20, 15
20, 24
20, 25
32, 18
32, 24
32, 15
32, 25
Upvotes: 1