向字典中添加条目(如果它不存在)

2024-04-19 05:47:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图写一些代码来计算2的幂,但是将它们存储在一个以10的幂为键的字典中,因此,例如,2^9将存储为

{0:2, 1:1, 2:5}

其中有5*10^2+1*10^1+2*10^0。在

所以现在,我有一些

^{pr2}$

问题是

result.setdefault(p+1,result[p]/10)

它覆盖result[p+1]中的任何内容。我知道有可能只检查字典,然后在需要时“初始化”新的密钥,但是有没有更优雅的方法可以随时执行呢?我可以将结果初始化为足够长,但由于我不一定知道“足够长”有多长,所以在我看来,动态扩展它更有意义。在

基本上我想买一些

for p in result.keys():
    if result[p] / 10 != 0:
        if result[p+1] exists:
            result[p+1]+=result[p]/10
        else:
            create result[p+1] and set its value to result[p]/10

非常感谢任何帮助!在


Tags: 方法代码in内容forif字典exists
2条回答

所以,每次在主循环中所做的是:每个数字加倍,然后将额外的十位数加到下一个数字。问题是,对于最高的数字,下一个数字是不存在的。在

所以这里有一个解决方案,尽管它对除2以外的任何功率都不起作用,原因如下。在

def foo():
    result={0:2}
    for i in range(2,10):
        for p in result.keys():
            result[p]*=2
        for p in result.keys()[:]:
            if result[p] / 10 != 0:
                result[p+1] = result.get(p+1, 0) + result[p] / 10
                result[p] = result[p] % 10

与原始代码相比,有两个关键更改。在

首先,我们必须将[:]添加到第二个result.keys()的末尾,以便在循环之前迭代字典的一组键,而不是它的当前键。原因是,如果最后一个数字是>;5,我们将向字典中添加一个新的键,并且不允许您在遍历它时这样做。(为什么?有几个原因,但最简单的一个原因是字典的顺序是任意的,而且每次添加一个键,整个顺序都会改变。这在以后也很重要。)

第二,你最初的问题是:如何避免不得不检查if p+1 in result来决定是存储r_p还是将r_p添加到现有值中?在

在处理计数时,使用collection.Counter,它与dict类似,只是它只存储整数,任何缺少的键都有一个值0。否则,您通常使用collection.defaultdict,它与dict类似,只是您可以指定一个所有缺少的键都具有的默认值。使用Counter或{},您只需要result[p+1] += result[p]/10。在

但是我使用了另一种替代方法:在dict上使用get方法,它允许您指定一个默认值。稍后我将解释原因,但请记住,通常情况下,当您发现自己在寻找get时,您可能需要defaultdict或{}。在

所以,现在它将运行,并且工作,为2的幂次。但它对其他国家无效,原因有二:

首先,我们按随机顺序进行运载。对于2的幂次,你最多只能携带一个1,而1不可能影响上一个数字是否携带。(8不能携带,8+1也不能,现在有办法得到9。)但是对于任何其他的力量,这是不正确的。在

在简单的测试中,您可能不会注意到这一点,因为当您从一个空的dict开始并按排序顺序添加少量的小键(实际上,具有小散列值的键,但自身具有小的int散列值)时(至少在CPython 2.7和3.2中是如此),并且不会删除任何内容,dict通常会按顺序迭代(并打印)。但总的来说,顺序是不可预测的,你不能依赖它。在

这个问题的解决方案是使用collections.OrderedDict,它按照键的添加顺序迭代这些键。这就是为什么我不想使用defaultdictCounter:因为如果你必须切换到OrderedDict,你唯一的选择就是get。在

第二,一旦你的指数超过10,你可能需要携带100。这意味着你必须携带10,这将导致下一个数字携带,即使它是0。这意味着我们不能只是提前复制钥匙。例如,假设我们做的是75次方幂。从^{开始。将每个数字乘以75到{0:375, 1:525}。现在拿着37:{0:5, 1:562}。现在携带56:{0:5, 1:2, 2:56}。因为我们只迭代原始密钥的副本,即[0, 1]-我们没有机会携带5。在

我让你来解决这个问题。在

但是,您可能需要考虑的一件事是创建一个新字典,而不是在适当的地方修改旧字典。然后你就可以解决所有这些问题了。(一般来说,使用纯函数而不是改变状态可以避免很多问题,但当然要付出额外复制的代价。)

^{pr2}$

您可以使用in语法检查是否存在密钥:

for p in result.keys()[:]:
    r_p = result[p] / 10

    if r_p != 0:
        if p + 1 in result:
            result[p + 1] += r_p
        else:
            result[p + 1] = r_p

或者,您可以使用Counter,它会自动执行以下操作:

^{pr2}$

另外,你的情况有点奇怪。result[p] / 10 == 0仅当python2上的result[p] < 10或python3上的result[p] == 0。在

相关问题 更多 >