如何在没有覆盖的情况下将键/值对插入到嵌套的dict中?

时间:2013-07-29 19:02:51

标签: python python-2.7

我是使用Python 2.75的新程序员

我有一个名为by_sale的嵌套词典,格式如下:

{sale : {days_elapsed: daily_sales_amount}}.

例如:

{'Spring Savings 0413' : {1 : 3000, 2: 2000, 4:1000}, 
 'Back to School 0812' : {1: 4000, 3:3000, 4:2000}}

请注意,“春季储蓄0413”没有第3天,“重返校园0812”没有第2天。

我试图创建一个名为by_day的新词典,它将存储每一天的销售总额,即使是没有新销售的天数,也就是这样:

{1: {'Spring Savings 0413': 3000, 'Back to School 0812': 4000}, 
 2: {'Spring Savings 0413': 5000, 'Back to School 0812': 4000}, 
 3: {'Spring Savings 0413': 5000, 'Back to School 0812': 7000}, 
 4: {'Spring Savings 0413': 6000, 'Back to School 0812': 9000}}

这是我的代码:

by_day = {}
for sale in by_sale.iterkeys():
    running_total = 0
    for i in range(1,4): #check for each day in the first 4 days
        by_day[i] = {} #initialize a nested blank dictionary for each day
        daily_amount = by_sale[sale].get(i,0) #grab the amount for the day, if none, return a zero
        running_total += daily_amount
        by_day[i][sale] = running # --> I know this is my problem... but why?
print by_day

我得到的只是上次销售的价值,似乎覆盖了其他销售数据:

{1: {'Back to School 0812': 4000}, 
 2: {'Back to School 0812': 4000}, 
 3: {'Back to School 0812': 7000}, 
 4: {'Back to School 0812': 9000}}

我有点了解这里发生的事情......我无法弄清楚如何阻止它发生。任何指针都将非常感谢!

2 个答案:

答案 0 :(得分:2)

此处没有defaultdict的解决方案:

d = {'Spring Savings 0413' : {1 : 3000, 2: 2000, 4:1000}, 
 'Back to School 0812' : {1: 4000, 3:3000, 4:2000}}

r = {}

for s, l in d.items():
    for i in range(1, 5):
        if i not in r: r[i] = {}
        r[i][s] = l.get(i, 0) + r.get(i - 1, {}).get(s, 0)

{1: {'Back to School 0812': 4000, 'Spring Savings 0413': 3000},
 2: {'Back to School 0812': 4000, 'Spring Savings 0413': 5000},
 3: {'Back to School 0812': 7000, 'Spring Savings 0413': 5000},
 4: {'Back to School 0812': 9000, 'Spring Savings 0413': 6000}}

答案 1 :(得分:1)

您正在使用by_day[i] = {}覆盖每个循环上每个键的条目。您应该检查是否存在密钥,在这种情况下,您应该更新现有的密码。

或者,使用collections.defaultdict

>>> by_sale = {'Spring Savings 0413' : {1 : 3000, 2: 2000, 4:1000}, 'Back to School 0812' : {1: 4000, 3:3000, 4:2000}}
>>> 
>>> 
>>> from collections import defaultdict
>>> 
>>> by_day = defaultdict(dict)
>>> for sale, sale_info in by_sale.iteritems():
...     running_total = 0
...     for i in range(1,5):
...         daily_amount = sale_info.get(i,0)
...         running_total += daily_amount
...         by_day[i].update({sale:running_total})
... 
>>> 
>>> dict(by_day)
{1: {'Spring Savings 0413': 3000, 'Back to School 0812': 4000}, 
 2: {'Spring Savings 0413': 5000, 'Back to School 0812': 4000}, 
 3: {'Spring Savings 0413': 5000, 'Back to School 0812': 7000}, 
 4: {'Spring Savings 0413': 6000, 'Back to School 0812': 9000}}

您应该使用range(1, 5)代替。 range(1, 4)给出了 - [1, 2, 3]