让我们假设我有一个(文本)文件具有以下结构(名称,分数):
a 0 a 1 b 0 c 0 d 3 b 2
等等.我的目标是将每个名字的分数相加,并从最高分到最低分.所以在这种情况下,我想要以下输出:
d 3 b 2 a 1 c 0
事先我不知道文件中会有什么名字.
我想知道是否有一种有效的方法来做到这一点.我的文本文件最多可包含50,000个条目.
我能想到的唯一方法就是从第1行开始,记住该名称,然后查看整个文件以查找该名称和总和.这看起来非常低效,所以我想知道是否有更好的方法来做到这一点.
将所有数据读入字典:
from collections import defaultdict from operator import itemgetter scores = defaultdict(int) with open('my_file.txt') as fobj: for line in fobj: name, score = line.split() scores[name] += int(score)
和排序:
for name, score in sorted(scores.items(), key=itemgetter(1), reverse=True): print(name, score)
打印:
d 3 b 2 a 1 c 0性能
为了检查这个答案与@SvenMarnach的答案的性能,我将两种方法都放入一个函数中.这fobj
是一个打开阅读的文件.我使用io.StringIO
这样的IO延迟应该,希望不被测量:
from collections import Counter def counter(fobj): scores = Counter() fobj.seek(0) for line in fobj: key, score = line.split() scores.update({key: int(score)}) return scores.most_common() from collections import defaultdict from operator import itemgetter def default(fobj): scores = defaultdict(int) fobj.seek(0) for line in fobj: name, score = line.split() scores[name] += int(score) return sorted(scores.items(), key=itemgetter(1), reverse=True)
结果collections.Counter
:
%timeit counter(fobj) 10000 loops, best of 3: 59.1 µs per loop
结果collections.defaultdict
:
%timeit default(fobj) 10000 loops, best of 3: 15.8 µs per loop
看起来defaultdict
快了四倍.我不会猜到这一点.但是在性能方面你需要衡量.
这是一个很好的用例collections.Counter
:
from collections import Counter scores = Counter() with open('my_file') as f: for line in f: key, score = line.split() scores.update({key: int(score)}) for key, score in scores.most_common(): print(key, score)