如何使用相同的方法按不同的属性快速排序对象列表?
How to quick sort list of objects by different attributes using the same method?
我的class如下:
class Member:
def __init__(self, name, zip, hire_date, birth_date):
self.id = id
self.name = name
self.zip = zip
self.hire_date = hire_date
self.birth_date = birth_date
def get_name(self):
return self.name
def get_birth_date(self):
return self.birth_date
def get_hire_date(self):
return self.hire_date
def get_zip_code(self):
return self.zip
我需要根据邮政编码、姓名、birth_date 和 hire_date 快速排序此 class 对象的列表。我可以使用单独的排序方法来实现这些。例如,按邮政编码快速排序:
def partition(array, begin, end):
pivot = begin
for i in range(begin+1, end+1):
if array[i].get_zip_code() <= array[begin].get_zip_code():
pivot += 1
array[i], array[pivot] = array[pivot], array[i]
array[pivot], array[begin] = array[begin], array[pivot]
return pivot
def quicksort(array, begin=0, end=None):
if end is None:
end = len(array) - 1
def _quicksort(array, begin, end):
if begin >= end:
return
pivot = partition(array, begin, end)
_quicksort(array, begin, pivot-1)
_quicksort(array, pivot+1, end)
return _quicksort(array, begin, end)
这很好用。但是现在我如何使相同的方法适用于所有属性;理想情况下,通过将附加参数传递给 quicksort()
来定义要排序的属性。我也希望不直接调用对象属性,而是使用 getter 方法。
这是按邮政编码排序后的输出
Name Zip Hire Date Birth Date
Cosmo Kramer 111-222 2019-06-01 1979-08-12
George Costanza 131-212 2016-06-01 1980-08-12
Jerry Seinfeld 223-212 2017-06-01 1981-06-15
John Wayne 323-212 2018-06-01 1962-06-17
您可以通过在 class 中定义另一个方法来实现此目的:
class Metric:
b_date = "birth_date"
h_date = "hire_date"
zip_code = "zip_code"
name = "name"
class Member:
def __init__(self, name, zip, hire_date, birth_date):
self.id = id
self.name = name
self.zip = zip
self.hire_date = hire_date
self.birth_date = birth_date
def get_name(self):
return self.name
def get_birth_date(self):
return self.birth_date
def get_hire_date(self):
return self.hire_date
def get_zip_code(self):
return self.zip
def get_metric_value(self, metric):
if metric == Metric.b_date:
return self.get_birth_date()
elif metric == Metric.h_date:
return self.get_hire_date()
elif metric == Metric.zip_code:
return self.get_zip_code()
elif metric == Metric.name:
return self.get_name()
def partition(array, begin, end, metric):
pivot = begin
for i in range(begin+1, end+1):
if array[i].get_metric_value(metric) <= array[begin].get_metric_value(metric):
pivot += 1
array[i], array[pivot] = array[pivot], array[i]
array[pivot], array[begin] = array[begin], array[pivot]
return pivot
def quicksort(array, metric, begin=0, end=None):
if end is None:
end = len(array) - 1
def _quicksort(array, begin, end):
if begin >= end:
return
pivot = partition(array, begin, end, metric)
_quicksort(array, begin, pivot-1)
_quicksort(array, pivot+1, end)
return _quicksort(array, begin, end)
quicksort(array, Metric.zip_code) # or any other metric ...
添加另一个参数,指示要排序的 key
,或者只使用执行相同操作的 built-in sort()
方法:
class Member:
def __init__(self, name, zip, hire_date, birth_date):
self.id = id
self.name = name
self.zip = zip
self.hire_date = hire_date
self.birth_date = birth_date
def get_name(self):
return self.name
def get_birth_date(self):
return self.birth_date
def get_hire_date(self):
return self.hire_date
def get_zip_code(self):
return self.zip
# Define how to print a Member
def __str__(self):
return f'{self.name:15} {self.zip} {self.hire_date} {self.birth_date}'
def partition(array, key, begin, end):
pivot = begin
for i in range(begin+1, end+1):
if key(array[i]) <= key(array[begin]): # use key for comparison
pivot += 1
array[i], array[pivot] = array[pivot], array[i]
array[pivot], array[begin] = array[begin], array[pivot]
return pivot
def quicksort(array, key, begin=0, end=None):
if end is None:
end = len(array) - 1
def _quicksort(array, key, begin, end):
if begin >= end:
return
pivot = partition(array, key, begin, end)
_quicksort(array, key, begin, pivot-1)
_quicksort(array, key, pivot+1, end)
return _quicksort(array, key, begin, end)
def display(L):
print('Name Zip Hire Date Birth Date')
for item in L:
print(item)
print()
L =[Member('Cosmo Kramer','111-222','2019-06-01','1979-08-12'),
Member('George Costanza','131-212','2016-06-01','1980-08-12'),
Member('Jerry Seinfeld','223-212','2017-06-01','1981-06-15'),
Member('John Wayne','323-212','2018-06-01','1962-06-17')]
quicksort(L,Member.get_hire_date)
display(L)
quicksort(L,Member.get_birth_date)
display(L)
# Using built-in sort()
L.sort(key=Member.get_name)
display(L)
输出:
Name Zip Hire Date Birth Date
George Costanza 131-212 2016-06-01 1980-08-12
Jerry Seinfeld 223-212 2017-06-01 1981-06-15
John Wayne 323-212 2018-06-01 1962-06-17
Cosmo Kramer 111-222 2019-06-01 1979-08-12
Name Zip Hire Date Birth Date
John Wayne 323-212 2018-06-01 1962-06-17
Cosmo Kramer 111-222 2019-06-01 1979-08-12
George Costanza 131-212 2016-06-01 1980-08-12
Jerry Seinfeld 223-212 2017-06-01 1981-06-15
Name Zip Hire Date Birth Date
Cosmo Kramer 111-222 2019-06-01 1979-08-12
George Costanza 131-212 2016-06-01 1980-08-12
Jerry Seinfeld 223-212 2017-06-01 1981-06-15
John Wayne 323-212 2018-06-01 1962-06-17
参考Python自带排序功能的实现:
def identity(x):
return x
def partition(array, begin, end, key):
pivot = begin
for i in range(begin+1, end+1):
if key(array[i]) <= key(array[begin]):
pivot += 1
array[i], array[pivot] = array[pivot], array[i]
array[pivot], array[begin] = array[begin], array[pivot]
return pivot
def quicksort(array, begin=0, end=None, key=identity):
if end is None:
end = len(array) - 1
def _quicksort(array, begin, end):
if begin >= end:
return
pivot = partition(array, begin, end, key)
_quicksort(array, begin, pivot-1)
_quicksort(array, pivot+1, end)
return _quicksort(array, begin, end)
用法:
quicksort(list_of_member, key=Member.get_name)
quicksort(list_of_member, key=Member.get_zip_code)
我的class如下:
class Member:
def __init__(self, name, zip, hire_date, birth_date):
self.id = id
self.name = name
self.zip = zip
self.hire_date = hire_date
self.birth_date = birth_date
def get_name(self):
return self.name
def get_birth_date(self):
return self.birth_date
def get_hire_date(self):
return self.hire_date
def get_zip_code(self):
return self.zip
我需要根据邮政编码、姓名、birth_date 和 hire_date 快速排序此 class 对象的列表。我可以使用单独的排序方法来实现这些。例如,按邮政编码快速排序:
def partition(array, begin, end):
pivot = begin
for i in range(begin+1, end+1):
if array[i].get_zip_code() <= array[begin].get_zip_code():
pivot += 1
array[i], array[pivot] = array[pivot], array[i]
array[pivot], array[begin] = array[begin], array[pivot]
return pivot
def quicksort(array, begin=0, end=None):
if end is None:
end = len(array) - 1
def _quicksort(array, begin, end):
if begin >= end:
return
pivot = partition(array, begin, end)
_quicksort(array, begin, pivot-1)
_quicksort(array, pivot+1, end)
return _quicksort(array, begin, end)
这很好用。但是现在我如何使相同的方法适用于所有属性;理想情况下,通过将附加参数传递给 quicksort()
来定义要排序的属性。我也希望不直接调用对象属性,而是使用 getter 方法。
这是按邮政编码排序后的输出
Name Zip Hire Date Birth Date
Cosmo Kramer 111-222 2019-06-01 1979-08-12
George Costanza 131-212 2016-06-01 1980-08-12
Jerry Seinfeld 223-212 2017-06-01 1981-06-15
John Wayne 323-212 2018-06-01 1962-06-17
您可以通过在 class 中定义另一个方法来实现此目的:
class Metric:
b_date = "birth_date"
h_date = "hire_date"
zip_code = "zip_code"
name = "name"
class Member:
def __init__(self, name, zip, hire_date, birth_date):
self.id = id
self.name = name
self.zip = zip
self.hire_date = hire_date
self.birth_date = birth_date
def get_name(self):
return self.name
def get_birth_date(self):
return self.birth_date
def get_hire_date(self):
return self.hire_date
def get_zip_code(self):
return self.zip
def get_metric_value(self, metric):
if metric == Metric.b_date:
return self.get_birth_date()
elif metric == Metric.h_date:
return self.get_hire_date()
elif metric == Metric.zip_code:
return self.get_zip_code()
elif metric == Metric.name:
return self.get_name()
def partition(array, begin, end, metric):
pivot = begin
for i in range(begin+1, end+1):
if array[i].get_metric_value(metric) <= array[begin].get_metric_value(metric):
pivot += 1
array[i], array[pivot] = array[pivot], array[i]
array[pivot], array[begin] = array[begin], array[pivot]
return pivot
def quicksort(array, metric, begin=0, end=None):
if end is None:
end = len(array) - 1
def _quicksort(array, begin, end):
if begin >= end:
return
pivot = partition(array, begin, end, metric)
_quicksort(array, begin, pivot-1)
_quicksort(array, pivot+1, end)
return _quicksort(array, begin, end)
quicksort(array, Metric.zip_code) # or any other metric ...
添加另一个参数,指示要排序的 key
,或者只使用执行相同操作的 built-in sort()
方法:
class Member:
def __init__(self, name, zip, hire_date, birth_date):
self.id = id
self.name = name
self.zip = zip
self.hire_date = hire_date
self.birth_date = birth_date
def get_name(self):
return self.name
def get_birth_date(self):
return self.birth_date
def get_hire_date(self):
return self.hire_date
def get_zip_code(self):
return self.zip
# Define how to print a Member
def __str__(self):
return f'{self.name:15} {self.zip} {self.hire_date} {self.birth_date}'
def partition(array, key, begin, end):
pivot = begin
for i in range(begin+1, end+1):
if key(array[i]) <= key(array[begin]): # use key for comparison
pivot += 1
array[i], array[pivot] = array[pivot], array[i]
array[pivot], array[begin] = array[begin], array[pivot]
return pivot
def quicksort(array, key, begin=0, end=None):
if end is None:
end = len(array) - 1
def _quicksort(array, key, begin, end):
if begin >= end:
return
pivot = partition(array, key, begin, end)
_quicksort(array, key, begin, pivot-1)
_quicksort(array, key, pivot+1, end)
return _quicksort(array, key, begin, end)
def display(L):
print('Name Zip Hire Date Birth Date')
for item in L:
print(item)
print()
L =[Member('Cosmo Kramer','111-222','2019-06-01','1979-08-12'),
Member('George Costanza','131-212','2016-06-01','1980-08-12'),
Member('Jerry Seinfeld','223-212','2017-06-01','1981-06-15'),
Member('John Wayne','323-212','2018-06-01','1962-06-17')]
quicksort(L,Member.get_hire_date)
display(L)
quicksort(L,Member.get_birth_date)
display(L)
# Using built-in sort()
L.sort(key=Member.get_name)
display(L)
输出:
Name Zip Hire Date Birth Date
George Costanza 131-212 2016-06-01 1980-08-12
Jerry Seinfeld 223-212 2017-06-01 1981-06-15
John Wayne 323-212 2018-06-01 1962-06-17
Cosmo Kramer 111-222 2019-06-01 1979-08-12
Name Zip Hire Date Birth Date
John Wayne 323-212 2018-06-01 1962-06-17
Cosmo Kramer 111-222 2019-06-01 1979-08-12
George Costanza 131-212 2016-06-01 1980-08-12
Jerry Seinfeld 223-212 2017-06-01 1981-06-15
Name Zip Hire Date Birth Date
Cosmo Kramer 111-222 2019-06-01 1979-08-12
George Costanza 131-212 2016-06-01 1980-08-12
Jerry Seinfeld 223-212 2017-06-01 1981-06-15
John Wayne 323-212 2018-06-01 1962-06-17
参考Python自带排序功能的实现:
def identity(x):
return x
def partition(array, begin, end, key):
pivot = begin
for i in range(begin+1, end+1):
if key(array[i]) <= key(array[begin]):
pivot += 1
array[i], array[pivot] = array[pivot], array[i]
array[pivot], array[begin] = array[begin], array[pivot]
return pivot
def quicksort(array, begin=0, end=None, key=identity):
if end is None:
end = len(array) - 1
def _quicksort(array, begin, end):
if begin >= end:
return
pivot = partition(array, begin, end, key)
_quicksort(array, begin, pivot-1)
_quicksort(array, pivot+1, end)
return _quicksort(array, begin, end)
用法:
quicksort(list_of_member, key=Member.get_name)
quicksort(list_of_member, key=Member.get_zip_code)