当前位置:  开发笔记 > 编程语言 > 正文

在列表推导中增加多个for循环的时间

如何解决《在列表推导中增加多个for循环的时间》经验,为你挑选了1个好方法。



1> N. Wouda..:

所以,我从你当前的方法开始,发现虽然它确实有效,但它很慢.我的第一次尝试只涉及将列表理解转换为适合numpy数组的方法.这比你原来的方法快了大约三倍,但是当我注意到一些非常漂亮的东西时:这是一个对称的Toeplitz矩阵.从那个维基页面:

在线性代数中,以Otto Toeplitz命名的Toeplitz矩阵或对角线常数矩阵是一个矩阵,其中每个从左到右的下降对角线是恒定的.

我首先使用scipy了Toeplitz矩阵的默认实现,但这种方法对于你的问题来说是不必要的.所以我给自己写了一个类似的方法,这是下面的第三次尝试.

方法

我为每种方法运行了10次测试,每次测试包含1000次运行.我将参数设置为m = 10, n = 100.结果可以在下表中找到:

    Your approach       Numpy #1     Numpy #2     Numpy #3
1        4.573965       1.432406     1.060242     0.186767
2        4.341466       1.432237     1.060404     0.186872
3        4.442438       1.434460     1.144850     0.183120
4        4.318919       1.456928     1.072072     0.185626
5        4.249392       1.450684     1.072217     0.183273
6        4.202730       1.508863     1.070299     0.183019
7        4.224226       1.457543     1.065354     0.183591
8        4.234505       1.432971     1.082438     0.185711
9        4.256538       1.431828     1.080051     0.184290
10       4.241055       1.557204     1.083070     0.185845

AVG      4.308523       1.459512     1.079100     0.184811
STD      0.117433       0.041693     0.024538     0.001521

scipy托普利茨方法(Numpy #2在表)比你目前的方法快近四倍,但所有这些结果由第三个也是最后的方法相形见绌:高达23倍以上的初步实施加快!

现在,既然你对时间的复杂性感兴趣,我就会n变化,保持m = 10.每种方法的结果可以在下图中找到:

不同方法的时间复杂性.

显然,第三种方法是要走的路!

完整代码:

import timeit
import numpy as np
from scipy.linalg import toeplitz


def your_approach(m, n):
    print("\n\tlist comprehension")
    k = range(m, n)
    for i in range(1, 11):
        start = timeit.default_timer()
        for j in range(1, 1001):
            data_list_comp = [[(k1 - k2) ** 2 for k2 in k] for k1 in k]
        print("\t{}".format(timeit.default_timer() - start))
    return data_list_comp


def numpy1(m, n):
    print("\n\tnumpy")
    k_n = np.array(range(m, n))
    for i in range(1, 11):
        start = timeit.default_timer()
        for j in range(1, 1001):
            data_numpy = [list((k_n - x) ** 2) for x in k_n]
        print("\t{}".format(timeit.default_timer() - start))
    return data_numpy


def numpy2(m, n):
    print("\n\ttoeplitz")
    k_n = np.array(range(0, n - m)) ** 2
    toep = toeplitz(k_n)
    for i in range(1, 11):
        start = timeit.default_timer()
        for j in range(1, 1001):
            data_numpy = [list(toep[:, i]) for i in range(n - m)]
        print("\t{}".format(timeit.default_timer() - start))
    return data_numpy

def numpy3(m, n):
    print("\n\ttoeplitz2")
    k_n = list(np.array(range(0, n - m)) ** 2)  # can obviously be done without numpy, but I was a bit lazy. :)
    for i in range(1, 11):
        start = timeit.default_timer()
        for j in range(1, 1001):
            data_numpy = [(k_n[i::-1] + k_n[1:-i]) if i != 0 else k_n for i in range(0, n - m)]
        print("\t{}".format(timeit.default_timer() - start))
    return data_numpy

m = 10

for n in [25, 50, 100, 150, 200]:
    assert your_approach(m, n) == numpy1(m, n) == numpy2(m, n) == numpy3(m, n)

推荐阅读
mylvfamily
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有