柜台类扩展

时间:2013-03-14 20:09:09

标签: auto-increment

我在找到一种优雅的方法来创建一个可以:

的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}}}。但我坚持从键列表创建这个任意嵌套字典。任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:0)

有两种可能性。

首先,您可以使用由Counter s构成的“关键路径”的平面tuple伪造嵌套关键字:

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

但是你需要写一个str - 替换 - 或者更好的是,一个实现__str__的包装类。当你在它的时候,你可以轻松编写一个incr包装器,让你可以使用你想要的API:

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

或者,您可以在嵌套Counter之上构建自己的dict类。 Counter的代码是用纯Python编写的,而the source非常简单易读。

从您的代码开始,您似乎无需在任何地方访问counter[key2][key3]等内容,这意味着第一个可能更简单,更合适。

答案 1 :(得分: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}}}

答案 2 :(得分: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}