【问题标题】:Which is faster and why? Set or List?哪个更快,为什么?设置还是列出?
【发布时间】:2011-12-04 17:52:44
【问题描述】:

假设我有一个图表,想看看b in N[a]。哪个实现更快?为什么?

a, b = range(2)
N = [set([b]), set([a,b])]

或

N= [[b],[a,b]]

这显然过于简单了,但想象一下图变得非常密集。

【问题讨论】:

    标签: python list graph set


    【解决方案1】:

    集合中的成员资格测试要快得多,尤其是对于大型集合。这是因为该集合使用hash function 映射到存储桶。由于 Python 实现会自动调整该哈希表的大小,因此无论集合大小如何(假设哈希函数足够好),速度都可以保持恒定 (O(1))。

    相比之下,要评估一个对象是否是列表的成员,Python 必须比较每个成员的相等性,即测试是 O(n)。

    【讨论】:

    • 打败我。还值得指出的是,OP 在第一个示例中有一个列表列表,在第二个示例中有一个集合列表。因为外层容器在这两种情况下都是一个列表,所以在这两种情况下搜索都是 O(n)。
    • Python 集合是动态调整大小的哈希表,因此无论项目数量如何,您都可以得到分期 O(1)。 @gddc OP 询问关于N 容器列表中单个项目 (b in N[a]) 的成员资格测试,所以不,它不是O(n)。
    • @delnan 你说得对,O(1) (+notes) 比 O(log n) (-notes) 更好。
    • @phihag O(1) 不仅比 O(log n) 好:O(1) 是正确的,O(log n) 不是。
    • @NedBatchelder:实际上,如果你查看数学定义,你会发现只要 O(1) 为常数,O(log N) 就是正确的——如果它是常数,它也以 log N 为界. 所以 O(1) 是“刚好”比 O(log N) 好。
    【解决方案2】:

    这完全取决于您要完成的工作。逐字使用您的示例,使用列表会更快,因为您不必经历创建集合的开销:

    import timeit
    
    def use_sets(a, b):
        return [set([b]), set([a, b])]
    
    def use_lists(a, b):
        return [[b], [a, b]]
    
    t=timeit.Timer("use_sets(a, b)", """from __main__ import use_sets
    a, b = range(2)""")
    print "use_sets()", t.timeit(number=1000000)
    
    t=timeit.Timer("use_lists(a, b)", """from __main__ import use_lists
    a, b = range(2)""")
    print "use_lists()", t.timeit(number=1000000)
    

    生产:

    use_sets() 1.57522511482
    use_lists() 0.783344984055
    

    但是,由于这里已经提到的原因,当您搜索大型集合时,您会受益于使用集合。通过您的示例无法判断拐点对您来说在哪里以及您是否会看到好处。

    我建议您对这两种方式都进行测试,并为您的特定用例选择更快的方法。

    【讨论】:

      【解决方案3】:

      Set(我的意思是像 HashSet 这样的基于散列的集合)比 List 查找值要快得多。 List 必须按顺序查找该值是否存在。 HashSet 几乎可以在恒定时间内直接跳转定位桶查找值。

      【讨论】:

        猜你喜欢
        • 2010-11-15
        • 1970-01-01
        • 2014-05-16
        • 2011-03-26
        • 2012-06-12
        • 2010-09-29
        • 2011-03-14
        • 2012-07-15
        • 2011-09-22
        相关资源
        最近更新 更多