【发布时间】:2012-01-13 22:16:54
【问题描述】:
给定一个文件如下所示:
1440927 1
1727557 3
1440927 2
9917156 4
第一个字段是一个 ID,即in range(0, 200000000)。第二个字段表示一个类型,即in range(1, 5)。并且类型 1 和类型 2 属于一个共同的类别S1,而类型 3 和类型 4 属于S2。一个 ID 可能有多个不同类型的记录。该文件大小约为 200MB。
问题是统计记录类型为 1 或 2 的 ID 的数量,以及数量 具有类型 3 或 4 记录的 ID。
我的代码:
def gen(path):
line_count = 0
for line in open(path):
tmp = line.split()
id = int(tmp[0])
yield id, int(tmp[1])
max_id = 200000000
S1 = bitarray.bitarray(max_id)
S2 = bitarray.bitarray(max_id)
for id, type in gen(path):
if type != 3 and type != 4:
S1[id] = True
else:
S2[id] = True
print S1.count(), S2.count()
虽然它给出了答案,但我认为它运行得有点慢。我应该怎么做才能让它运行得更快?
编辑:
文件中有重复记录。而我只需要区分S1(类型1和类型2)和S2(类型3和类型4)。例如,1440927 1 和1440927 2 只计算一次,而不是两次,因为它们属于 S1。所以我必须存储 ID。
【问题讨论】:
-
您可以使用分析器。您可以删除
id=int( ...并改用yield int(tmp[0], ...。您可以使用if type <= 2而不是两个比较。您可以完全删除生成器并将代码内联到with open( ... ) as f:块中。试一试。下面的评论也有一个好点,关于 bitarray ^^ -
您有什么理由使用位数组来标记索引吗?否则,您可以简单地增加一个计数器,而不是将条目设置为“True”。这应该可以提高性能。
-
+1 使用分析器。瓶颈在哪里?是S1和S2的分配吗?另外,请考虑以下问题:(几乎)0-200000000 中的所有数字都存在吗?如果不是,请考虑另一种数据类型。每个id可以出现多次吗?如果没有,请考虑完全放弃阵列并仅使用计数器。或者也许这是一个您已经有了最佳解决方案的问题。对于非常大的文件,您的瓶颈很可能是磁盘 I/O,这将需要您购买更好的磁盘进行优化。
-
@Boris 我必须存储 ID,因为有重复的记录。例如,在文件样本 1440927 中,应该只计算一次,而不是两次。因为类型 1 和类型 2 都属于 S1。
标签: python performance bitarray