从OrderedDict获取密钥计数,其中key是一个元组 [英] Get key count from OrderedDict where key is a tuple
问题描述
我有一个这样的字典:
my_dict=collections.OrderedDict([((123, 1), 'qwe'), ((232, 1), 'asd'), ((234, 2), 'zxc'), ((6745, 2), 'aaa'), ((456, 3), 'bbb')])
元组的组合始终是唯一的,我希望保持以下顺序插入,因此是OrderedDict。字典里我有超过1万个项目。如何有效维护一个计数器,该计数器给出元组中第二个元素的计数?基本上,每当我想在键中添加/删除项目时,我都需要知道计数。现在,我只是遍历 my_dict
并每次获得计数器 ,但是这样做似乎很昂贵。
The combination of the tuple is always unique and I would like to maintain the order of insertion, and hence OrderedDict. I've a well over ~10K items in the dict. How can I efficiently maintain a counter that gives the count of the second element in the tuple? Basically, I need to know the count whenever I would like to add/delete an item in the key. Right now I just iterate through my_dict
and get the counter everytime but it seems to be very expensive to do that.
在上面的示例中,我希望输出为:
In the above example I want the output to be:
1:2 # As in 1 occurs 2 times
2:2
3:1
现在我做了以下内容:
from collections import OrderedDict, Counter
my_dict = OrderedDict()
my_dict[(123,1)] = 'qwe'
my_dict[(232,1)] = 'asd'
my_dict[(234,2)] = 'zxc'
my_dict[(6745,2)] = 'aaa'
my_dict[(456,3)] = 'bbb'
cnt = []
for item in my_dict.keys():
cnt.append(item[1])
print Counter(cnt)
我不确定这是最好的方法,但是有一种方法可以覆盖 =
运算符和 pop
函数,以便添加还是每次执行该操作时都减去一个计数?
I'm not sure if this is the best way but is there a way to override the the =
operator and pop
function, such that it adds or subtracts a count every time I do that operation?
推荐答案
获取 Counter
与 OrderedDict
配合使用可能需要一些子类。这可能会起作用(我只实现了 __ setitem __
和 __ getitem __
,但是如果您想要一个更强大的实现,让我知道):
Getting a Counter
to work nicely with an OrderedDict
is probably going to require some subclassing. Here's something that might work (I've only implemented __setitem__
and __getitem__
, but if you'd like a more robust implementation, let me know):
import collections
class CountedOrderedDict(collections.OrderedDict):
def __init__(self, *args, **kwargs):
self.counter = collections.Counter()
super(CountedOrderedDict, self).__init__(*args, **kwargs)
def __delitem__(self, key):
super(CountedOrderedDict, self).__delitem__(key)
self.counter[key[1]] -= 1
def __setitem__(self, key, value):
if key not in self:
self.counter[key[1]] += 1
super(CountedOrderedDict, self).__setitem__(key, value)
示例用法:
>>> my_dict = CountedOrderedDict({(123,1): 'sda', (232,1) : 'bfd', (234,2) : 'csd', (6745,2) : 'ds', (456,3) : 'rd'})
>>> my_dict.counter
Counter({'1': 2, '2': 2, '3': 1})
>>> del my_dict[(123,1)]
>>> my_dict.counter
Counter({'2': 2, '1': 1, '3': 1})
>>> my_dict[(150,1)] = "asdf"
>>> my_dict.counter
Counter({'1': 2, '2': 2, '3': 1})
这是一个更通用的 CountedOrderedDict
实现,它以键函数作为参数。
Here's a more general CountedOrderedDict
implementation that takes a key function as a parameter.
import collections
class CountedOrderedDict(collections.OrderedDict):
def __init__(self, key=lambda k: k, *args, **kwargs):
self.counter = collections.Counter()
self.key_transform = key
super(CountedOrderedDict, self).__init__(*args, **kwargs)
def __delitem__(self, key):
super(CountedOrderedDict, self).__delitem__(key)
self.counter[self.key_transform(key)] -= 1
def __setitem__(self, key, value):
if key not in self:
self.counter[self.key_transform(key)] += 1
super(CountedOrderedDict, self).__setitem__(key, value)
对于您的需求,您可以像这样实例化:
For your needs, you'd instantiate it like so:
my_dict = CountedOrderedDict(key=lambda k: k[1])
这篇关于从OrderedDict获取密钥计数,其中key是一个元组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!