通过字段名称sortingnamedtuples列表的Pythonic方法

我想sorting命名元组列表,而不必记住字段名的索引。 我的解决scheme看起来很尴尬,希望有人会有一个更优雅的解决scheme。

from operator import itemgetter from collections import namedtuple Person = namedtuple('Person', 'name age score') seq = [ Person(name='nick', age=23, score=100), Person(name='bob', age=25, score=200), ] # sort list by name print(sorted(seq, key=itemgetter(Person._fields.index('name')))) # sort list by age print(sorted(seq, key=itemgetter(Person._fields.index('age')))) 

谢谢,尼克

 from operator import attrgetter from collections import namedtuple Person = namedtuple('Person', 'name age score') seq = [Person(name='nick', age=23, score=100), Person(name='bob', age=25, score=200)] 

按名称sorting列表

 sorted(seq, key=attrgetter('name')) 

按年龄sorting

 sorted(seq, key=attrgetter('age')) 
 sorted(seq, key=lambda x: x.name) sorted(seq, key=lambda x: x.age) 

我testing了这里给出的两种方法的速度,因为@zenpoy关心的是性能。

testing脚本:

 import random from collections import namedtuple from timeit import timeit from operator import attrgetter runs = 10000 size = 10000 random.seed = 42 Person = namedtuple('Person', 'name,age') seq = [Person(str(random.randint(0, 10 ** 10)), random.randint(0, 100)) for _ in range(size)] def attrgetter_test_name(): return sorted(seq.copy(), key=attrgetter('name')) def attrgetter_test_age(): return sorted(seq.copy(), key=attrgetter('age')) def lambda_test_name(): return sorted(seq.copy(), key=lambda x: x.name) def lambda_test_age(): return sorted(seq.copy(), key=lambda x: x.age) print('attrgetter_test_name', timeit(stmt=attrgetter_test_name, number=runs)) print('attrgetter_test_age', timeit(stmt=attrgetter_test_age, number=runs)) print('lambda_test_name', timeit(stmt=lambda_test_name, number=runs)) print('lambda_test_age', timeit(stmt=lambda_test_age, number=runs)) 

结果:

 attrgetter_test_name 44.26793992166096 attrgetter_test_age 31.98247099677627 lambda_test_name 47.97959511074551 lambda_test_age 35.69356267603864 

使用lambda确实比较慢。 速度降低了10%。

编辑

进一步testing显示使用多个属性进行sorting时的结果。 添加了以下两个testing用例相同的设置:

 def attrgetter_test_both(): return sorted(seq.copy(), key=attrgetter('age', 'name')) def lambda_test_both(): return sorted(seq.copy(), key=lambda x: (x.age, x.name)) print('attrgetter_test_both', timeit(stmt=attrgetter_test_both, number=runs)) print('lambda_test_both', timeit(stmt=lambda_test_both, number=runs)) 

结果:

 attrgetter_test_both 92.80101586919373 lambda_test_both 96.85089983147456 

Lambda仍然performance不佳,但不如此。 现在慢了大约5%。

testing是在Python 3.6.0上完成的。

Interesting Posts