Без какой-либо выборки или эталона данных сложно воспроизвести ваши наблюдения. Я пытался с:
from random import randint
data_file = [[randint(0, 15) for _ in range(20)] for _ in range(100000)]
flag_1 = 1
flag_2 = 2
flag_3 = 3
flag_4 = 4
И обычный l oop был в два раза быстрее, чем четыре списка понимания (см. Тест ниже).
Если вы хотите улучшить скорость процесс, у вас есть несколько отведений.
Перечисления и обычные l oop
Если flag_n
- строки, и вы уверены, что row[0]
является одним из них для каждого row
, тогда вы можете проверить один символ вместо всей строки. Например:
flag_1 = "first flag"
flag_2 = "second flag"
flag_3 = "third flag"
flag_4 = "fourth flag"
Посмотрите на вторые символы: f<I>rst, S<E>cond, T<H>ird, F<O>urth
. Вы просто должны проверить, если row[0][1] == 'i'
(или 'e'
или 'h'
или 'o'
) вместо row[0] == flag_n
.
Regular l oop
Если вы хотите улучшить скорость обычного l oop, у вас есть несколько отведений.
Во всех случаях
Вы можете назначить flag = row[0]
вместо получения row[0]
первых элементов четыре раза. Это основа c, но она работает.
Если у вас есть информация о данных
Если данные отсортированы по флагу, вы, очевидно, можете сразу создать flag_n_set
: найдите сначала последний flag_n
и напишите flag_n_set = list(range(first_flag_n_index, last_flag_n_index+1))
.
Если вы знаете частоту флагов, вы можете приказать if ... elif ...
elif ... elif ... else
сначала проверить более частый флаг, затем второй по частоте флаг, и т. д. c.
Вы также можете использовать диктовку, чтобы избежать последовательности if ... elif ...
. Если у вас не слишком много строк, которые не соответствуют ни одному флагу, вы можете использовать defaultdict
:
from collections import defaultdict
def test_append_default_dict():
flag_set = defaultdict(list)
for i, row in enumerate(data_file):
flag_set[row[0]].append(i)
return tuple(flag_set[f] for f in (flag_1, flag_2, flag_3, flag_4))
Тесты с данными выше:
test_list_comprehensions 3.8617278739984613
test_append 1.9978336450003553
test_append_default_dict 1.4595633919998363