【问题标题】:How to build a list faster than .append?如何比 .append 更快地构建列表?
【发布时间】:2021-01-05 04:30:25
【问题描述】:

我试过这个代码

p = 1000003
q = 400003
M = p*q  
n = 84480
X = [6225**2%M]
new = X[0]**2%M
i = 1
while new not in X and len(X) < n:
         X.append(new)
         new = X[i]**2%M
         i += 1

.append 语法需要一段时间来构建列表。我需要另一种语法来更快地创建列表,因为n 非常大。

【问题讨论】:

    标签: python list performance append


    【解决方案1】:

    你可以试试 Python 的 extend() 方法,它比 append 更快。 对于大型列表,extend() 方法的运行时间比append() 方法的运行时间快 60%。 more info

    【讨论】:

    • 扩展如何提高性能?他每一步只添加一个元素,因此 extend 将像 append 一样工作
    • @Glauco 对于较大的列表大小,extend() 方法应该更快,因为 Python 可以将元素批量追加到列表中,而不是一次又一次地调用相同的方法。
    • 我同意你的观点,但是在这个算法中他一次只插入一个项目
    • @Glauco 他在他的问题中说“我需要另一种语法来更快地创建列表,因为 n 非常大。”所以这就是为什么我建议他尝试extend()
    【解决方案2】:

    如果您不在运行时实例化或更改对象,Python 会很好地工作,因此如果您首先创建 所有 元素,您可以简单地重新分配值。 但是这个算法缺少 [new in X] 部分,这是因为这是 O(NxM)。

    所以最好的解决方案是在之前创建所有元素以避免追加,并使用更好的数据结构来检查值是否已经完成,这是一个字典:

    p = 1000003
    q = 400003
    M = p*q  
    n = 84480
    X = [6225**2%M]*n
    Xd = {X[0]:None}
    new = X[0]**2%M
    i = 1
    while new not in Xd and i<n:
             X[i] = new
             Xd[new]=None
             new = X[i]**2%M
             i += 1
    
    
    
    Original:
    CPU times: user 47.5 s, sys: 13.2 ms, total: 47.5 s
    Wall time: 49.5 s
    
    Optimized:
    CPU times: user 66.9 ms, sys: 9 µs, total: 66.9 ms
    Wall time: 103 ms
    

    【讨论】:

    • 我明白了,重点是在开头构建列表。非常感谢兄弟
    • 但是,现在我有 1 个列表和 1 个元组,这不是需要一段时间吗?
    • 这不是一个元组,而是一个字典,对于 in 操作来说速度非常快。 (x in [] 需要 O(n)) ( x in {} 需要 O(1)) 所以这是第二个改进。
    【解决方案3】:

    您的问题不在于追加,而在于您检查是否存在重复条目的方式。您可以使用一组非常有效地做到这一点。

    您还可以将代码构建为生成器,使其更易于使用和重用:

    def modSquare(N,M,maxCount):
        seen = set()
        for _ in range(maxCount):
            N = N**2%M
            if N in seen: break
            yield N
            seen.add(N)
    

    输出:

    p = 1000003
    q = 400003
    M = p*q  
    n = 84480
    X = list(modSquare(6225,M,n))
    
    print(len(X)) 
    # 84480
    
    print(X[:3],"...",X[-3:])
    # [38750625, 395175256848, 7948406859] ... [166985992167, 267628307961, 385065196277]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-28
      • 2021-01-29
      • 2019-08-31
      • 2019-11-30
      • 1970-01-01
      • 2018-07-28
      • 2020-11-23
      相关资源
      最近更新 更多