情景:计算日志文件中,独立IP的个数,也就是unique visitor。
计算量:每小时大概有70万左右的记录,每天24小时,大概1400-1500万条记录
一开始,想到用一个list来保存客户端IP,从日志里边取出一个IP,
判断是否已经存在,如果存在,就忽略,否则添加到这个list中去
addrs = []
for line in f.readlines() :
addr = get_addr(line)
if not addr in addrs :
addrs.append(addr)
print len(addrs)
满以为这样就可以做好了,可是,实际中一测试,分析完一个小时的文件要7分半钟,
照这种速度,24个文件要2个多小时,实在是太慢了!
由此可以看到list的in的效率是非常低的,在元素数量很少的情况下,看不出来,但是元素一多
马上就看到了。
联想到Java里边有Set,HashSet使用元素的hash值来判断是否重复,速度应该是快很多,那么
Python里边是否也有set呢。哈哈,查了一下manual,还好,连名字都一样叫做set
将上边代码里边的list换成set
addrs = set()
for line in f.readlines():
addr = get_addr(line)
addrs.add(addr)
print len(addrs)
set的add方法会在内部判断元素是否已经添加,如果元素已经存在,则忽略掉,否则就添加到set里边去
所以,不需要像list那样在添加到set之前判断。
测试了一下,分析完一个文件才要2-3秒钟,速度是用list的200多倍啊,24个文件用了1分钟就分析完了。
set的缺点在于无法保证元素添加进去的顺序,如果需要保证顺序,还需要list的辅助啦。