python - 如何在Numpy中重写double for循环以节省执行时间?

我想以最有效的方式创建卡片组。这是带有double for循环和标准列表的简单解决方案:

card = []
for figure in range(2, 15):
    for suite in [1, 2, 3, 4]:
        card = [figure, suite]
        self.cards.append(card)


该代码将执行数百万次,因此我想使用Numpy对其进行优化。

EDIT1:我什至认为是否写下所有可能性并将它们放入数组中并不是最快的。

最佳答案

有人在评论中击败了我,但我为您提供了一些时间信息。请注意,您的时间可能会有所不同,但是相对时间应该可以很好地代表您可能会看到的效果。

首先是您的代码,我将其固定为可运行:

cards = []
for figure in range(2, 15):
    for suite in [1, 2, 3, 4]:
        card = [figure, suite]
        cards.append(card)
# 8.04 µs ± 27.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)


所以8.04微秒才是最好的时机!使用 numpy.mgrid

import numpy as np
cards = np.mgrid[1:5, 2:15]
# 20.5 µs ± 320 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)


出人意料的慢得多。我想知道是否在我的系统上没有为numpy设置理想的设置。我仍然建议在您的系统上尝试(使用Jupyter笔记本中的 %%timeit单元魔术来进行概要分析)。

接下来使用 itertools.product

import itertools as it
figures = range(2, 15)
suits = [1, 2, 3, 4]
cards = list(it.product(suits, figures))
# 2.5 µs ± 27.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)


快点!最好的消息是 it.product()返回一个迭代器,而不是在调用时创建列表,因此,如果您直到以后都不需要实际的卡片列表,则可以推迟创建列表,而只需传递迭代器即可。到目前为止,创建迭代器是最快的:

cards_it = it.product(suits, figures)  # notice no 'list'
# 479 ns ± 9.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)


那比其他任何东西快5到10倍!