Ignore unorderable data type while sorting tuple
我正在从一本书中自学python,我一直在做编程练习。练习的目的是列出对象,然后根据一些对象属性对这些对象进行排序。
我的教科书的作者说,在排序过程中,使用一个键来调用类方法来进行每次比较,可以减慢大型数据集的排序时间,并且在构建列表时,通过对每个对象只调用一次类方法来构建"修饰"列表,可以提高后续排序的效率。编程问题规定,我应该生成一系列元组,而不是键,其中tuple元素0是对象属性的文字值,tuple元素1是对象本身。在我有了装饰列表之后,我可以使用内置的列表排序方法(例如"sorted()"或".sort()"等)将其全部排序。
当两个对象具有相同的排序属性值时,我会得到一个错误。此示例代码将重现错误:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class Shrubber: def __init__(self, age): self.name = 'Roger' self.age = age def getAge(self): return self.age def main(): rogerAges = [30, 21, 21, 25] rogers = [] for rAge in rogerAges: newShr = Shrubber(rAge) rogers.append((newShr.getAge(), newShr)) rogers.sort() print(rogers) main() |
我希望程序打印如下内容:
1 | [(21, <__main__.Shrubber object at XxXEX>), (21, <__main__.Shrubber object at YxYEY>), (25, <__main__.Shrubber object at ZxZEZ>), (30, <__main__.Shrubber object at QxQEQ>)] |
号
…但是,它给了我一个类型错误:
1 | TypeError: unorderable types: Shrubber() < Shrubber() |
我确信我得到了这个错误,因为在Python遇到两个元组元素0的相同值之后,它查找元素1并找到一个无序的数据类型(对象)。然而,两个灌木不能同龄的限制让我看起来好像错过了什么。
我的问题是:我能按tuple元素0稳定地对tuple列表排序,并忽略不可排序的tuple元素1吗?
如果确保比较永远无法通过灌木对象,则不必实现
1 2 3 4 5 6 7 8 | def main(): rogerAges = [30, 21, 21, 25] rogers = list() for i, rAge in enumerate(rogerAges): newShr = Shrubber(rAge) rogers.append((newShr.getAge(), i, newShr)) rogers.sort() print(rogers) |
但是,从所有的角度来看,这都是错误的,您应该使用
最后一点要注意的是,以这种方式添加到列表中并不是Python式的方式。您可以这样做:
1 2 3 4 5 | def main(): rogerAges = [30, 21, 21, 25] rogers = [(rAge, i, Shrubber(rAge)) for (i, rAge) in enumerate(rogerAges)] rogers.sort() print(rogers) |
。
在这些情况下,我不知道如何让它忽略第二个元素。另一种方法是向对象的类中添加一个方法,该方法将返回所需的信息。这样做可以避免需要pass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class Shrubber: def __init__(self, age): self.name = 'Roger' self.age = age def getAge(self): return self.age def __lt__(self, other): # added comparison method return self.age < other.age def main(): rogerAges = [30, 21, 21, 25] rogers = [] for rAge in rogerAges: newShr = Shrubber(rAge) rogers.append((newShr.getAge(), newShr)) rogers.sort() print(rogers) if __name__ == '__main__': main() |
输出(为可读性而包装):
1 2 3 4 | [(21, <__main__.Shrubber object at 0x00C1D830>), (21, <__main__.Shrubber object at 0x00C1D9D0>), (25, <__main__.Shrubber object at 0x00C1DA30>), (30, <__main__.Shrubber object at 0x00C1D9F0>)] |
号