2015-11-06 1 views
-1

Я хочу эффективно скопировать словарь на defaultdict.
Вот мой код:Копирование словаря по умолчаниюdict

[In] from collections import defaultdict 
[In] new_dict = {'a': 1, 'b': 2, 'c': 3, 'e':4, 'f':5} 
[In] def_dict = defaultdict(list) 
[In] timeit for k, v in new_dict.items(): def_dict[k].append(v) 
[Out] 1000000 loops, best of 3: 910 ns per loop 

Я хочу, чтобы улучшить производительность этого. Любые предложения приветствуются.

+0

Как вы будете знать, когда производительность достаточно хорошо? –

+0

@PeterWood По производительности я имел в виду время, затраченное на выполнение функции. –

+0

оптимизация с какой целью? – morels

ответ

1

Я согласен с тем, что использование def_dict[k] = [v] будет быстрее, чем def_dict[k].append(v), на основе моего собственного тестирования, которое находит его почти в два раза быстрее.

Ниже приведен полный код маркировки, который я использовал для определения этого. Я также попробовал пару других возможностей, но никто не был лучше.

Аналогичные результаты были получены как с Python 3.5.0, так и с Python 2.7.10.

from __future__ import print_function 
import sys 
from textwrap import dedent 
import timeit 

N = 1000000 # number of executions of each "algorithm" 
R = 3 # number of Repeations of executions 

# common setup for all algorithms (not timed) 
setup = dedent(""" 
    from collections import defaultdict 

    new_dict = {'a': 1, 'b': 2, 'c': 3, 'e': 4, 'f': 5} 
""") 

algorithms = { 
    "def_dict[k].append(v)": dedent(""" 
     def_dict = defaultdict(list) 
     for k, v in new_dict.items(): def_dict[k].append(v) 
    """), 

    "def_dict[k] = [v]": dedent(""" 
     def_dict = defaultdict(list) 
     for k, v in new_dict.items(): def_dict[k] = [v] 
    """), 

    "defaultdict(list, <gen-xprsn>)": dedent(""" 
     def_dict = defaultdict(list, ((k, [v]) for k, v in new_dict.items())) 
     """), 

    "defaultdict(list, <dict-comp>)": dedent(""" 
     def_dict = defaultdict(list, {k:[v] for k, v in new_dict.items()}) 
     """), 
} 

# collecting results of executing and timing each algorithm snippet 
timings = [ 
    (label, 
    min(timeit.repeat(algorithms[label], setup=setup, repeat=R, number=N)), 
    ) for label in algorithms 
] 

# display results 
print('fastest to slowest execution speeds (Python {}.{}.{})\n'.format(
     *sys.version_info[:3]), 
     ' ({:,d} executions, best of {:d} repetitions)\n'.format(N, R)) 

longest = max(len(timing[0]) for timing in timings) # length of longest label 
ranked = sorted(timings, key=lambda t: t[1]) # ascending sort by execution time 
fastest = ranked[0][1] 
for timing in ranked: 
    print("{:>{width}} : {:9.6f} secs, rel speed {:4.2f}x, {:6.2f}% slower". 
      format(timing[0], timing[1], round(timing[1]/fastest, 2), 
        round((timing[1]/fastest - 1) * 100, 2), width=longest)) 

Вот результаты выполнения на моей системе:

fastest to slowest execution speeds (Python 3.5.0) 
    (1,000,000 executions, best of 3 repetitions) 

      def_dict[k] = [v] : 0.977644 secs, rel speed 1.00x, 0.00% slower 
defaultdict(list, <dict-comp>) : 1.330040 secs, rel speed 1.36x, 36.05% slower 
defaultdict(list, <gen-xprsn>) : 1.761532 secs, rel speed 1.80x, 80.18% slower 
     def_dict[k].append(v) : 1.929081 secs, rel speed 1.97x, 97.32% slower 
+0

Но третий результат будет другим. У вас не будет значений в списках. –

+1

@Peter: Хорошая точка ... не могу поверить, что я пропустил это. См. Обновленный ответ. – martineau

Смежные вопросы