1

У меня есть следующее, которое анализирует три столбца табличных данных (рабочий стол openpyxl) в defaultdict.Применение понимания словаря к defaultdict

def campaigns_and_adsets_and_pageviews_from_ga(ourTab): 
    d = defaultdict(lambda: defaultdict(int)) 
    for row in ourTab.rows[1:-1]: 
     if ('Facebook' in row[0].value) and ('(not set)' not in row[2].value): 
      d[row[1].value][row[2].value] += row[4].value 
    return d 

Выходной сигнал, который выглядит следующим образом:

In [790]: campaigns_and_adsets_and_pageviews_from_ga(ourTab) 
Out[790]: 
defaultdict(<function __main__.<lambda>>, 
      {u'XXX 20160314': defaultdict(int, 
         {u'Carnival desktopfeed': 2.0, 
          u'Carnival mobilefeed': 588.0, 
          u'PYS Broad desktopfeed': 371.0, 
          u'PYS Broad mobilefeed': 1192.0}), 
      u'YYY Intl 20150903': defaultdict(int, 
         {u'CA desktopfeed': 2.0}), 

То, что я хочу сделать, это умножить конечное значение в каждом элементе (то есть 2,0, 588,0 и т.д.) с константой, в результате чего другой defaultdict (или даже обычный вложенный dict будет в порядке).

Можно ли деконструировать defaultdict как-то обратно во вложенный dict, чтобы позволить преобразование быть возможным? Или какие другие подходы возможны?

+4

Вы забыли вызвать функцию. –

+4

Вам нужно '.items()', так что вы действительно работаете через записи. –

+2

Ввиду того, что сразу были обнаружены две ошибки, я предлагаю вам сначала добавить/помечать вашу функцию 'campaign_and_adsets_and_pageviews_from_ga', чтобы возвращать только словарный литерал, определяющий вложенные словари (не обращая внимания на defaultdict'):' return {u'XXX 20160314 ': {u'Carnival desktopfeed ': 2.0, ...}} '. Затем напишите код, который правильно копирует его и удваивает числа. Затем вернитесь к возврату 'defaultdict' с вычисленными результатами. Таким образом, вы не будете отвлекаться, полагая, что все, что пойдет не так, должно быть связано с 'defaultdict' :-) –

ответ

3

Вы можете использовать простую рекурсивную функцию, которая умножает число с заданным значением и для каждого dict экземпляра создает новый словарь:

from numbers import Number 

def multiply(o, mul): 
    if isinstance(o, dict): 
     return {k: multiply(v, mul) for k, v in o.items()} 
    elif isinstance(o, Number): 
     return o * mul 
    else: 
     return o 

Учитывая ваш пример defaultdict и мультипликатор 2 в качестве входных данных выходных выглядят следующим:

{ 
    u'YYY Intl 20150903': {u'CA desktopfeed': 4.0}, 
    u'XXX 20160314': { 
     u'Carnival desktopfeed': 4.0, 
     u'PYS Broad desktopfeed': 742.0, 
     u'PYS Broad mobilefeed': 2384.0, 
     u'Carnival mobilefeed': 1176.0 
    } 
} 

Обратите внимание, что пример не работает со списками, для тех, кому нужно добавить еще какой-нибудь код.

+1

Теперь * это * мышление вне коробки. Не знал о модуле 'numbers'. Благодарю вас на обоих фронтах. – Pyderman

+0

@Pyderman: Придется искать его тоже после того, как я понял, что должен быть более простой путь, чем обработка 'float' и' int' отдельно. – niemmi