[英]defaultdict of defaultdict?
Is there a way to have a defaultdict(defaultdict(int))
in order to make the following code work?有没有办法让
defaultdict(defaultdict(int))
使以下代码工作?
for x in stuff:
d[x.a][x.b] += x.c_int
d
needs to be built ad-hoc, depending on xa
and xb
elements. d
需要临时构建,具体取决于xa
和xb
元素。
I could use:我可以使用:
for x in stuff:
d[x.a,x.b] += x.c_int
but then I wouldn't be able to use:但那时我将无法使用:
d.keys()
d[x.a].keys()
Yes like this:是这样的:
defaultdict(lambda: defaultdict(int))
The argument of a defaultdict
(in this case is lambda: defaultdict(int)
) will be called when you try to access a key that doesn't exist.当您尝试访问不存在的键时,将调用
defaultdict
的参数(在本例中为lambda: defaultdict(int)
)。 The return value of it will be set as the new value of this key, which means in our case the value of d[Key_doesnt_exist]
will be defaultdict(int)
.它的返回值将被设置为这个键的新值,这意味着在我们的例子中
d[Key_doesnt_exist]
的值将是defaultdict(int)
。
If you try to access a key from this last defaultdict ie d[Key_doesnt_exist][Key_doesnt_exist]
it will return 0, which is the return value of the argument of the last defaultdict ie int()
.如果您尝试从最后一个 defaultdict 访问一个键,即
d[Key_doesnt_exist][Key_doesnt_exist]
它将返回 0,这是最后一个 defaultdict 的参数的返回值,即int()
。
The parameter to the defaultdict constructor is the function which will be called for building new elements. defaultdict 构造函数的参数是将被调用以构建新元素的函数。 So let's use a lambda !
所以让我们使用 lambda !
>>> from collections import defaultdict
>>> d = defaultdict(lambda : defaultdict(int))
>>> print d[0]
defaultdict(<type 'int'>, {})
>>> print d[0]["x"]
0
Since Python 2.7, there's an even better solution using Counter :从 Python 2.7 开始, 使用 Counter有一个更好的解决方案:
>>> from collections import Counter
>>> c = Counter()
>>> c["goodbye"]+=1
>>> c["and thank you"]=42
>>> c["for the fish"]-=5
>>> c
Counter({'and thank you': 42, 'goodbye': 1, 'for the fish': -5})
Some bonus features一些奖励功能
>>> c.most_common()[:2]
[('and thank you', 42), ('goodbye', 1)]
For more information see PyMOTW - Collections - Container data types and Python Documentation - collections有关更多信息,请参阅PyMOTW - 集合 - 容器数据类型和Python 文档 - 集合
I find it slightly more elegant to use partial
:我发现使用
partial
稍微优雅partial
:
import functools
dd_int = functools.partial(defaultdict, int)
defaultdict(dd_int)
Of course, this is the same as a lambda.当然,这与 lambda 相同。
Previous answers have addressed how to make a two-levels or n-levels defaultdict
.以前的答案已经解决了如何制作两级或 n 级
defaultdict
。 In some cases you want an infinite one:在某些情况下,你想要一个无限的:
def ddict():
return defaultdict(ddict)
Usage:用法:
>>> d = ddict()
>>> d[1]['a'][True] = 0.5
>>> d[1]['b'] = 3
>>> import pprint; pprint.pprint(d)
defaultdict(<function ddict at 0x7fcac68bf048>,
{1: defaultdict(<function ddict at 0x7fcac68bf048>,
{'a': defaultdict(<function ddict at 0x7fcac68bf048>,
{True: 0.5}),
'b': 3})})
For reference, it's possible to implement a generic nested defaultdict
factory method through:作为参考,可以通过以下方式实现通用的嵌套
defaultdict
工厂方法:
from collections import defaultdict
from functools import partial
from itertools import repeat
def nested_defaultdict(default_factory, depth=1):
result = partial(defaultdict, default_factory)
for _ in repeat(None, depth - 1):
result = partial(defaultdict, result)
return result()
The depth defines the number of nested dictionary before the type defined in default_factory
is used.在使用
default_factory
定义的类型之前,深度定义了嵌套字典的数量。 For example:例如:
my_dict = nested_defaultdict(list, 3)
my_dict['a']['b']['c'].append('e')
Others have answered correctly your question of how to get the following to work:其他人已经正确回答了您关于如何使以下内容起作用的问题:
for x in stuff:
d[x.a][x.b] += x.c_int
An alternative would be to use tuples for keys:另一种方法是使用元组作为键:
d = defaultdict(int)
for x in stuff:
d[x.a,x.b] += x.c_int
# ^^^^^^^ tuple key
The nice thing about this approach is that it is simple and can be easily expanded.这种方法的好处是它很简单并且可以很容易地扩展。 If you need a mapping three levels deep, just use a three item tuple for the key.
如果您需要一个三层深的映射,只需使用一个三项元组作为键。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.