这被认为是检查两个字符串是否相互排列的有效方法吗?使用两个字典会有什么区别? Counter是否针对python进行了更优化?
我想我应该澄清,我发布此帖的原因是这条评论:Check if two unordered lists are equal提到通过使用sort(s1)== sort(s2)检查两个字符串是否相同更有效。由于这是o(nlog(n)),你会认为Counter会有更好的运行时间。
答案 0 :(得分:2)
在您引用的另一个问题中,J.F. Sebastian理论认为在几乎所有情况下使用sort
比使用Counter
更快,但他明智地指出,如果您真的在意,您应该衡量:“在实践中,它可能总是比collections.Counter()
更快(尽管渐近O(n)
时间比O(n*log(n))
更好.sort()
。如果重要的话,请测量它。”< / p>
这种测量如下所示。高点:
最多大约10^6
的列表大小,sort
更快。
随着列表大小的增加,这种优势逐渐减少。
这些实验使用具有许多离散值的列表。如果列表具有适度高的重复值百分比,则基准可能会有所不同。
这些测量表明,创建Counter
的开销通常大于仅对数据进行排序的成本。考虑这一点的一种方法是查看Counter
创建相对于log(n)
方法的sort
部分的开销。直到n
变得相当大,Counter
数据结构的算法优势才能开始得到足够的回报来证明这种开销。
但请记住:对于较小的数据大小,速度优势可能无关紧要 - 除非您以高音量重复操作。从这个角度来看,对于大多数用例而言,从代码设计的角度来看,“算法正确”的方法(使用Counter
)可能仍然会更好 - 因为如果数据很大,它会更快,如果数据很快就会更快数据很小。
代码:
import timeit, sys, random
from collections import Counter
def prep():
random.shuffle(xs)
random.shuffle(ys)
def use_counter():
prep()
return Counter(xs) == Counter(ys)
def use_sort():
prep()
xs.sort()
ys.sort()
return xs == ys
experiments = [
(3, 10, 100000),
(3, 100, 10000),
(3, 1000, 1000),
(3, 10000, 100),
(3, 100000, 10),
(3, 1000000, 1),
(1, 10000000, 1),
]
for e in experiments:
repeat, list_size, timeit_n = e
xs = list(range(list_size))
ys = list(range(list_size))
r1 = timeit.repeat(use_counter, repeat = repeat, number = timeit_n)
r2 = timeit.repeat(use_sort, repeat = repeat, number = timeit_n)
print
print e
print 'total ', sum(r1), sum(r2)
print 'm1/m2 ', min(r1) / min(r2)
示例输出(比率&gt; 1表示Counter
较慢):
(3, 10, 100000)
total 5.06751918793 2.15432405472
m1/m2 2.34850470872
(3, 100, 10000)
total 3.16299915314 2.06651735306
m1/m2 1.52879303981
(3, 1000, 1000)
total 3.017786026 2.42989587784
m1/m2 1.24086325316
(3, 10000, 100)
total 3.06426525116 2.74061489105
m1/m2 1.11802891855
(3, 100000, 10)
total 3.66198205948 3.35467290878
m1/m2 1.1028159291
(3, 1000000, 1)
total 5.19361901283 5.08777713776
m1/m2 1.03125948765
(1, 10000000, 1)
total 20.0118789673 24.6061840057
m1/m2 0.813286569044
答案 1 :(得分:1)
它是O(n),所以在理论上是有效的。 function print_doc_count(i){
var str= "collection" + i.toString();
db.collection(str).count(function(err, res){
if(!err){
console.log("docs in collection: "+str+" = "+res);
}
});
}
for(var i=1; i<=10; i++){
print_doc_count(i);
}
是一个字典子类,所以唯一的区别是你必须用Python构建字典,而不是让Counter
类(声称是“高 - 性能“所以我假设在C中实现”这样做。两者都是相同的大O,但Counter
会更快。
这是一个不同的大O,但对于短字符串,对两个字符串进行排序实际上比Counter
快四倍。