2013-03-14 95 views
0

我有找到一个优雅的方式来创建一个计数器()类,可以一个问题:反类扩展

  • 饲料中键的任意数量和返回基于密钥的这个名单上嵌套的字典。
  • 此嵌套字典的增量也是任意的。

例如:

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

理想,我希望得到的结果是这样的:{键:20,{KEY2:{KEY3:40}}}。但我坚持从键列表创建这个任意嵌套的字典。任何帮助表示赞赏。

+0

为什么你需要有钥匙拼图? – Blender 2013-03-14 20:12:35

回答

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} 
+0

@MengxiLu你说你会在不同的层次上汇总这些统计数据。用我的代码,数字只存储在最外面的'叶'上;你也应该照顾。如果你可以花一些时间编写自己的树状结构,允许在不遍历所有分支的情况下进行求和,那么效率会更高。 – thkang 2013-03-15 19:04:17

0

有两种可能性。

首先,你可以随时假嵌套密钥东西用平Counter与由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]) 

或者,您可以建立在一个嵌套dict顶自己Counter般类。 Counter的代码是用纯Python编写的,the source非常简单易读。

从你的代码看,你没有任何需要在任何地方访问像counter[key2][key3]这样的东西,这意味着第一个可能会变得更简单和更合适。

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}}}