Не.Это кажется , как если бы это использовалось в качестве диктата, это хорошая идея, но на самом деле это ужасная ловушка.Используйте collections.Counter
:
import counts
seen_dict = collections.Counter(ar)
или, если вы не хотите этого делать, придерживайтесь цикла.
Проблема с попыткой использованияДиктовое понимание заключается в том, что в этом случае нет хорошего способа поддерживать состояние или чередовать вычисления значений каждого ключа.Каждое значение должно быть вычислено в одном выражении.Напротив, лучший способ решить вашу проблему с подсчетом - сделать один проход через ar
и обновлять счет каждого элемента по мере продвижения.
Ограничения понимания приводят к ужасно неэффективным попыткам, таким как
seen_dict = {val: ar.count(val) for val in ar}
, который делает количество проходов на ar
равным длине ar
, или немного более эффективному, но все еще ужасно неоптимальному
seen_dict = {val: ar.count(val) for val in set(ar)}
, которое нужно только сделать len(set(ar))
проходит, или для людей , немного более знакомых со стандартной библиотекой ,
from itertools import groupby
seen_dict = {val: sum(1 for _ in group) for val, group in groupby(sorted(ar))}
, которая, по крайней мере, не является квадратичным временем, но все еще O (nlogn) для длины-n ar
.
Если мы запустим синхронизацию из этих четырех фрагментов с входом list(range(10000))
:
from collections import Counter
from itertools import groupby
from timeit import timeit
ar = list(range(10000))
print(timeit('Counter(ar)', number=1, globals=globals()))
print(timeit('{val: ar.count(val) for val in ar}', number=1, globals=globals()))
print(timeit('{val: ar.count(val) for val in set(ar)}', number=1, globals=globals()))
print(timeit('{val: sum(1 for _ in group) for val, group in groupby(sorted(ar))}',
number=1, globals=globals()))
Мы получим следующий вывод:
0.0005530156195163727
1.0503493696451187
1.0463058911263943
0.00422721728682518
Counter
заканчивается через полмисекунды, в то время как фрагменты count
занимают секунду.(Версия set
имеет меньшее время выполнения из-за какого-то эффекта первого запуска, замедляющего работу другой версии; переключение порядка версий set
и не set
обычно меняет относительную синхронизацию этих версийДедупликация set
не помогает в этом тесте, так как на входе нет дубликатов.)
Для более длинного ввода полагаться на count
было бы еще более непомерно дорого.Полагаясь на count
, можно легко потратить несколько дней на ввод, который Counter
все равно завершится менее чем за секунду.