繁体   English   中英

为什么Sort(s1)== Sort(s2)比Counter(s1)== Counter(s2)更好用

[英]Why is Sort(s1)==Sort(s2) better to use than Counter(s1)==Counter(s2)

这是否被视为检查两个字符串是否彼此置换的有效方法? 改用两个字典有什么区别? Counter更适合python吗?

我想我应该澄清一下,我发表这条评论的原因是这样的评论: 检查两个无序列表是否相等,提到使用sort(s1)== sort(s2)检查两个字符串是否相同更有效。这是o(nlog(n)),您将认为Counter的运行时间更好。

在您提到的另一个问题中, JF Sebastian认为在几乎所有情况下使用sort都会比使用Counter更快,但他明智地指出,如果您真的很在意,您应该进行以下测量:“在实践中,它可能总是比collections.Counter()更快。 collections.Counter() (尽管对于.sort()渐近O(n)时间比O(n*log(n))好。)请测量它,如果它很重要。”

如下所示。 重点:

  • 列表大小最多约为10^6sort速度更快。

  • 随着列表大小的增加,这种优势逐渐减少。

  • 这些实验使用具有许多离散值的列表。 如果列表中重复值的百分比较高,则基准可能会有所不同。

  • 这些测量表明,创建Counter的开销通常比仅对数据进行排序的开销要大。 考虑这种情况的一种方法是查看Counter创建相对于sort方法的log(n)部分的开销。 直到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)

输出示例(比率> 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

它是O(n),所以理论上很有效。 Counter 字典的子类,因此唯一的区别是您必须使用Python来构建字典,而不是让Counter类(被称为“高性能”,因此我假设是用C实现)来做到这一点。 两者都是相同的big-O,但Counter会更快。

这是一个不同的big-O,但是对两个字符串进行排序实际上比我的系统上对Counter字符串不足的Counter快大约四倍。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM