问题描述及解决
今天写了个简单的脚本,将有向图转换成无向图,其中有一定的转换规则,本身脚本没啥难度,但是麻烦在数据量很大,其中需要进行查询边是否存在边集之中。这个边集有200w的数量级,然后查询的次数是接近200w次。
我想当然的采用了list,每次在list中进行查询,结果跑了大半个小时,三分之一还没跑到(我估计8分之一都够呛)。
然后我就在想有没有办法能够缩短运行时间,我是觉得问题出在这个in上,然后在网上一查,果然是这个问题,并且也有解决的办法。
python中list对象的存储结构采用的是线性表,所以其查询复杂度是O(n),查询起来就很慢,在我的脚本中,它需要进行O(n^2)的查询,当这个n为200w时,自然就非常非常慢。而dict对象的存储结构采用的是hash表,其查询复杂度是O(1),所以就会快很多很多,最多快n呗,这个是太夸张了。
所以最终,针对该问题的解决是,将列表转换成字典,每次查询时直接查询字典就行。至于要考虑从列表到字典的转换时间,这个倒不用太过于考虑,因为刚才也说了是线性表,遍历的时候倒不会很慢。
direc_edges = list(directed_graph.edges)
direc_edges_dict = {
}
for each in direc_edges:#构建字典,为了便于查询direc_edges_dict[each] = 1#each是一个元组
for each in undirec_edges:start,end = eachweight = 0count += 1if(count%100000==0):print("当前进度:",count)if (start,end) in direc_edges_dict.keys():weight += 1if (end,start) in direc_edges_dict.keys():weight += 1
在更换成dict之后,速度明显提升,这么大型的数据,具体时间我没统计,切出去看了会儿新闻,回来一看就弄好了,总共也不超过8分钟吧,快的就很离谱。
所以以后大规模的数据,千万不要用list的in。