将元素插入字典的有效方式



是否有更简单的方法来编写此代码?

def insert(k, v)  # v can either be a single number or a list of numbers, and k may or may not exist in self.dict
if k in self.dict:
if isinstance(v, list):
for e in v:
self.dict[k].add(e)
else:
self.dict[k].add(v)
else:
self.dict[k] = {}
if isinstance(v, list):
for e in v:
self.dict[k].add(e)
else:
self.dict[k].add(v)

您可以使用defaultdict并将代码简化为

def insert(self, k, v): 
if isinstance(v, list):
self.dict[k]+=v
else:
self.dict[k].append(v)

注意,在这种情况下,字典需要定义为:

self.dict = defaultdict(list)

或者,如果你想将一个集合与你的密钥相关联,你可以将其更改为defaultdict(set)并使用:

def insert(self, k, v): 
if isinstance(v, list):
self.dict[k]|=set(v)
else:
self.dict[k].add(v)
def insert(k, v):
entries = self.dict.setdefault(k, set())
if isinstance(v, list):
entries.update(v)
else:
entries.add(v)

在不更改您使用的类型的情况下,您也可以在一行中执行以下操作:

def insert(k, v): 
d.setdefault(k, []).extend(v if isinstance(v, list) else [v])

或者,当使用集合时:

def insert(k, v): 
d.setdefault(k, set()).update(v if isinstance(v, list) else [v])

这里有一个关于问题的练习,展示了异常处理和有限递归的使用-这可能是最有效的方法。尽管代码"看起来"比其他解决方案更大,但它编译成的指令比其他解决方式更少:

>>> class Foo:
...     def __init__(self):
...         self.dict = {}
... 
...     def insert(self, k, v):
...         try:
...             self.dict[k].extend(v)  # <-- majority of accesses 
...                                     #     only execute this one line.
...         except KeyError:
...             self.dict[k] = []
...             self.insert(k, v)
...         except TypeError:
...             self.dict[k].extend([v])
...             
>>> f = Foo()
>>> f.insert('bob', 1)
>>> f.dict
{'bob': [1]}
>>> f.insert('bob', [3, 4])
>>> f.dict
{'bob': [1, 3, 4]}

我相信这将具有最快的性能,假设您的大多数数据都是偶尔只有个位数的数字列表。而且钥匙的变化不会太大。单行self.dict[k].extend(v)应该毫无例外地执行对对象的大多数访问。检查类型和测试条件不会产生额外的成本。即使个位数很频繁,添加它们的分支也会产生与类型检查大致相同的成本——只是这种实现并不是每次添加东西都必须进行类型检查。

最新更新