0

假设我想创建一个字典,将数字映射到以这些数字结尾的小于 100 的数字,如下所示:

d = {}
for i in range(100):
 r = i % 10
 if r in d:
  d[r] = d[r].append(i)
 else:
  d[r] = [i]
print d

首先,当 i 为 20 时, d[r] 显然是 NoneType 当我尝试附加到它时,会引发错误。为什么会这样?其次,我觉得我的方法效率低下,因为检查 r in d 是否没有传播的工作。像这样的东西会更好,我觉得:

case(d[r]) of 
   SOME(L) => d[r] = L.append(i)
 | NONE => d[r] = [i]

有没有办法在 python 中使用这种逻辑?

4

2 回答 2

1

首先,当 i 为 20 时, d[r] 显然是 NoneType 当我尝试附加到它时,会引发错误。为什么会这样?

这是因为下面的代码是错误的:

d[r] = d[r].append(i)

.append修改列表作为副作用,并返回None。因此,在将列表附加到之后,它会被丢弃并替换为None现在重新分配给d[r].

有没有办法在 python 中使用这种逻辑?

有多种 hack 可以使用,但这里没有一个是合适的。

相反,解决特定问题:“如果存在则修改字典值,否则创建新值”。这可以细化为“如果不存在则创建一个空的默认值,然后修改现在保证存在的值”。

您可以使用 来做到这一点.setdefault,或者更优雅地,您可以将字典替换为collections.defaultdict

from collections import defaultdict

d = defaultdict(list)
for i in range(100):
    r = i % 10
    d[r].append(i)

或者您可以解决更具体的问题:“创建具有给定模式的字典”,即将规则或公式应用于输入序列(在这种情况下,输入为range(100)

from itertools import groupby

def last_digit(i): return i % 10
d = {k: list(v) for k, v in groupby(sorted(range(100), key=last_digit), last_digit)}

或者,您可以利用range需要另一个参数来指定步长的事实来解决更具体的问题:

d = {i: range(i, 100, 10) for i in range(10)}
于 2012-05-18T05:19:23.237 回答
0

使用 Andrew 的建议d[r].append(i),您会得到想要的答案:

In [3]: d
Out[3]: 
{0: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90],
 1: [1, 11, 21, 31, 41, 51, 61, 71, 81, 91],
 2: [2, 12, 22, 32, 42, 52, 62, 72, 82, 92],
 3: [3, 13, 23, 33, 43, 53, 63, 73, 83, 93],
 4: [4, 14, 24, 34, 44, 54, 64, 74, 84, 94],
 5: [5, 15, 25, 35, 45, 55, 65, 75, 85, 95],
 6: [6, 16, 26, 36, 46, 56, 66, 76, 86, 96],
 7: [7, 17, 27, 37, 47, 57, 67, 77, 87, 97],
 8: [8, 18, 28, 38, 48, 58, 68, 78, 88, 98],
 9: [9, 19, 29, 39, 49, 59, 69, 79, 89, 99]}

你可以这样做:

In [7]: for onesdigit in range(10):
   ...:     d[onesdigit] = range(onesdigit, 100, 10)
于 2012-05-18T05:19:52.290 回答