繁体   English   中英

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

[英]efficient way to insert elements into a dictionary

有没有更简单的方法来编写这段代码?

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)应该毫无例外地执行大多数对对象的访问。 它不会产生额外的成本检查类型和测试条件。 即使单个数字很频繁,分支添加它们也会产生与类型检查相同的成本——除了这种实现不会在每次添加内容时强制进行类型检查。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM