如何从具有userID和pageID的大型日志文件中查找最常访问的3网页序列
给定访问的网页日志文件:
Userid PageID A 1 A 2 A 3 B 2 B 3 C 1 B 4 A 4
查找最常访问的页面ID访问顺序:
for A : 1-2-3, 2-3-4 for B : 2-3-4
所以,2-3-4是最常见的。
我的想法:
- 将文件的每个项目放入
map1<key:user_id, list >
。 - 当
list.size() == 3
,创建一个新的structthree_hits
来保存三个pageID。 - 将它放入
map2
。 - 然后,在map2中找到具有最大计数器值的项目。
声明:
struct three_hits { int f_page; int s_page; int t_page; }; map<string, list > map_hit; map map_t_hits;
扫描记录:
for each( record: r in log) { if(map_hit.count(r.userid) >0) { map_hit[r.uid].second.push_back(r.pageID); if(map_hit[r.uid].second.size() ==3) { list tmp=map_hit[r.uid].second; t_hits(tmp[0],tmp[1],tmp[2]); // O(n lg n) if( map_t_hits.count(t_hits) >0) map_t_hits[t_hits]++; else map_t_hits[t_hits]=1; } else { list tmp(r.pageID); map_hit[r.uid]=tmp; } } // O(n)
迭代map_t_hits
一次以找到具有最高值的键( t_hits
)。
地图的时间O(n lg n)和空间O(n) 。
更好的解决方案?
您可以考虑使用sort-merge执行此操作。 首先使用用户id的稳定排序将给定用户的所有序列放在一起,保持原始顺序。 然后对所有3个网页序列进行排序,最后计算相等序列的运行。 这也是O(n log n)。 它可能需要花费更多的时间在实践中,但如果使用内部存储器运行可能需要更少的存储,并且可以在外部存储器中运行,如果您在任何时候都有太多的数据存储。 它是否真的更好取决于你的具体情况的细节。