0

我在寻找一种创建 Counter() 类的优雅方法时遇到问题,该类可以:

  • 输入任意数量的键并根据此键列表返回嵌套字典。
  • 这个嵌套字典的增量也是任意的。

例如:

counter = Counter()
for line in fin:
    if a:
        counter.incr(key1, 1)
    else:
        counter.incr(key2, key3, 2)
print counter

理想情况下,我希望得到的结果如下所示:{key1 : 20, {key2 : {key3 : 40}}}。但是我被困在从键列表中创建这个任意嵌套字典。任何帮助表示赞赏。

4

3 回答 3

0

有两种可能性。

首先,您总是可以通过使用Counter带有由 s 组成的“键路径”的平面来伪造嵌套键的东西tuple

counter = Counter()
for line in fin:
    if a:
        counter.incr((key1,), 1)
    else:
        counter.incr((key2, key3), 2)

但是你需要编写一个str-replacement ——或者,更好的是,一个实现__str__. 当您使用它时,您可以轻松编写一个incr包装器,让您可以使用您想要的 API:

def incr(self, *args):
    super().incr(args[:-1], args[-1])

或者,您可以Counter在嵌套的dict. 的代码Counter是用纯 Python 编写的,源代码非常简单易读。

从您的代码来看,您似乎不需要访问counter[key2][key3]任何地方的东西,这意味着第一个可能会更简单,更合适。

于 2013-03-14T20:18:41.850 回答
0

对象中唯一可以存在的值类型Counter是 int,您将无法使用Counter.

这是使用普通字典 ( ) 执行此操作的一种方法counter = {}。首先,要更新增量单个键的值:

counter[key1] = counter.setdefault(key1, 0) + 1

或者对于任意键列表来创建嵌套结构:

tmp = counter
for key in key_list[:-1]:
    tmp = tmp.setdefault(key, {})
tmp[key_list[-1]] = tmp.setdefault(key_list[-1], 0) + 1

我可能会把它变成以下函数:

def incr(counter, val, *keys):
    tmp = counter
    for key in keys[:-1]:
        tmp = tmp.setdefault(key, {})
    tmp[keys[-1]] = tmp.setdefault(keys[-1], 0) + val

例子:

>>> counter = {}
>>> incr(counter, 1, 'a')
>>> counter
{'a': 1}
>>> incr(counter, 2, 'a')
>>> counter
{'a': 3}
>>> incr(counter, 2, 'b', 'c', 'd')
>>> counter
{'a': 3, 'b': {'c': {'d': 2}}}
>>> incr(counter, 3, 'b', 'c', 'd')
>>> counter
{'a': 3, 'b': {'c': {'d': 5}}}
于 2013-03-14T20:19:12.373 回答
0

您可以子类dict化并创建自己的嵌套结构。

这是我编写此类课程的尝试:

class Counter(dict):
    def incr(self, *args):
        if len(args) < 2:
            raise TypeError, "incr() takes at least 2 arguments (%d given)" %len(args)

        curr = self

        keys, count = args[:-1], args[-1]

        for depth, key in enumerate(keys, 1):
            if depth == len(keys):
                curr[key] = curr.setdefault(key, 0) + count
            else:
                curr = curr.setdefault(key, {})


counter = Counter()

counter.incr('key1', 1)
counter.incr('key2', 'key3', 2)
counter.incr('key1', 7)
print counter #{'key2': {'key3': 2}, 'key1': 8}
于 2013-03-14T20:20:18.887 回答