2015-12-04 3 views
1

events Считают, что здесь имеет около 48000 словарных объектов:python dict/list comprehension: почему он медленнее, чем для цикла?

keyed_events = { gid: [ r for r in events if r['gid'] == gid ] for gid in gidlist } 

составляет около 4x медленнее, чем:

keyed_events = {} 
for event in events: 
    gid = event['gid'] 
    if gid not in keyed_events: 
     keyed_events[gid] = [] 
    keyed_events[gid].append(event) 

хотя первый выглядит более эффективным. Почему он медленнее? Итерация через events каждый проход понимания диктата?

+0

Может '[г для г в событиях, если г [ 'GID'] == GID]' заменить 'filter'? Не уверен, что это будет такая же медлительность –

+0

Да: 'keyed_events = {gid: filter (lambda x: x ['gid'] == gid, events) для gid в gidlist}' дает вам такое же медленное время выполнения – Wells

+0

At хотя это «выглядит» * более * эффективным: D –

ответ

4
keyed_events = { gid: [ r for r in events if r['gid'] == gid ] for gid in gidlist } 

Список/ДИКТ понимание работает на len(gidlist)*len(events) количество раз, как он перебирает events внутри цикла по gidlist.

для цикла, с другой стороны, имеет только один цикл по events с gid not in keyed_events, который является O(1) операцию

0

Я думаю, это потому, что в этом фрагменте вы перебор как gidlist и events, но в первом методе, но повторяя только events.

полностью Я думаю, что внутренний инлайн for неэффективна

3

Ваш словарь список + понимание более точно соответствует этому коду:

keyed_events = {} 
for gid in gidlist: 
    for r in events: 
     if r['gid'] == gid: 
      keyed_events[gid].append(r) 

Обратите внимание, что петля является вдвойне вложенной. Вы перебираете все события для каждого gid.

более точное соответствие вашему итеративного кода будет таким:

keyed_events = itertools.groupby(events, 'gid') 
+1

'itertools.groupby' требует, чтобы группы были смежными. – user2357112

+0

Это действительно работает довольно хорошо: – Wells

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