@ Ответ AlexanderCécile не только более разборчивый, чем тот, который вы опубликовали, но и устраняет избыточные вычисления временного массива. Несмотря на это, похоже, что он не работает быстрее, чем ваш первоначальный подход.
Все приведенные ниже тайминги запускаются с предварительной настройкой
import numpy as np
np.random.seed(0xDEADBEEF)
a = np.random.randint(8, size=N)
N
, варьирующейся от 1e3 до 1e8в 10 раз. Я попробовал четыре варианта кода:
- CodePope:
result = a[2:][a[2:] > 4]
- AlexanderCécile:
s = a[2:]; result = s[s > 4]
- MadPhysicist1:
result = a[np.flatnonzero(a[2:]) + 2]
- MadPhysicist2:
result = a[(a > 4) & (np.arange(a.size) >= 2)]
Во всех случаях время было получено в командной строке путем запуска
python -m timeit -s 'import numpy as np; np.random.seed(0xDEADBEEF); a = np.random.randint(8, size=N)' '<X>'
Здесь N
было степеньюот 10 между 3 и 8 и <X>
одним из выражений выше. Времена следующие:
Методы № 1 и № 2 практически неразличимы. Что удивительно, так это то, что в диапазоне между ~ 5e3 и ~ 1e6 элементами метод № 3 выглядит немного, но заметно быстрее. Я бы не ожидал, что от модной индексации. Метод № 4, конечно, будет самым медленным.
Вот данные для полноты:
CodePope AlexanderCécile MadPhysicist1 MadPhysicist2
1000 3.77e-06 3.69e-06 5.48e-06 6.52e-06
10000 4.6e-05 4.59e-05 3.97e-05 5.93e-05
100000 0.000484 0.000483 0.0004 0.000592
1000000 0.00513 0.00515 0.00503 0.00675
10000000 0.0529 0.0525 0.0617 0.102
100000000 0.657 0.658 0.782 1.09