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可以以某種方式解構爲嵌套字典嗎?或者還有什麼其他方法可行?

+4

您忘記了調用該函數。 –

+4

你需要'.items()',所以你實際上正在處理條目。 –

+2

鑑於兩個錯誤被立即發現,我建議你先bodge/mock你的'campaigns_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

現在*這是*在盒子外思考。沒有意識到'數字'模塊。謝謝你的兩條戰線。 – Pyderman

+0

@Pyderman:在我發現需要比單獨處理'float'和'int'更簡單的方法之後,也必須搜索它。 – niemmi