python: быстрый способ накопить в словаре списки значений
есть задача:
дан список чисел, необходимо собрать словарь, в котором в качестве ключа выступает число из списка, а в качестве значения - список позиций данного числа в исходном списке
подскажите, есть ли более производительный код, чем решение в лоб:
res = dict()
for i, v in enumerate(arr):
if v in arr:
res[v].append(i)
else:
res[v] = [i]
если использовать get - это замедляет код в 2-3 раза:
res = dict()
for i, v in enumerate(arr):
res[v] = res.get(v, []) + [i]
Ответы (1 шт):
Автор решения: CrazyElf
→ Ссылка
Из того, что я попробовал на моих тестовых данных быстрее оказался defaultdict. Но вообще нужно всё-таки приводить параметры ваших данных: тип и размерность. На разных данных могут быть разные результаты.
import random
from collections import defaultdict
def func1(arr):
res = dict()
for i, v in enumerate(arr):
if v in res:
res[v].append(i)
else:
res[v] = [i]
def func2(arr):
res = dict()
for i, v in enumerate(arr):
res[v] = res.get(v, []) + [i]
def func3(arr):
res = dict()
for i, v in enumerate(arr):
res.setdefault(v, []).append(i)
def func4(arr):
res = defaultdict(list)
for i, v in enumerate(arr):
res[v].append(i)
arr = [random.randint(0, 100) for _ in range(1000)]
assert func1(arr) == func2(arr)
assert func2(arr) == func3(arr)
assert func3(arr) == func4(arr)
%timeit func1(arr)
%timeit func2(arr)
%timeit func3(arr)
%timeit func4(arr)
Вывод:
10000 loops, best of 5: 167 µs per loop
1000 loops, best of 5: 270 µs per loop
10000 loops, best of 5: 192 µs per loop
10000 loops, best of 5: 144 µs per loop
С itertools.groupby я что-то недоразобрался )
Так то хорошо бы ещё попробовать Numpy и Numba, но нужно знать, какие у вас данные.