在 Python 中以容器的形式添加 dict 中已经存在的键的值

  • 本文关键字:dict 存在 添加 Python python
  • 更新时间 :
  • 英文 :


是否有任何内置函数可以执行以下操作?

dictionary = {‘a’:1, ‘b’:2, ‘c’:3}
dictionary.update(c=10)
# what happens
dictionary  ---- {‘a’:1, ‘b’:2, ‘c’:10}
# what I want to happen:
dictionary  ---- {‘a’:1, ‘b’:2, ‘c’:(3, 10)}

默认情况下,如果键相同,则较晚的键将覆盖较早的键。 如果 dict 中已经存在该键,则新键:值对的值将以容器的形式添加到现有值中,例如元组、列表或集合。

我可以编写一个辅助函数来做到这一点,但我相信它应该是这个问题的内置功能。

你可以这样做

from collections import defaultdict
d = defaultdict(list)
d["a"].append(1)
d["b"].append(2)
d["c"].append(3)
d["c"].append(10)
print(d)

结果

defaultdict(list, {'a': [1], 'b': [2], 'c': [3, 10]})

您想要的解决方案不是很优雅,所以我将提出一个替代方案。

  1. 元组是不可变的。让我们改用列表,因为我们可以轻松地附加到它们。
  2. 值的数据类型应一致。在任何情况下都使用列表,即使是单个值。
  3. 让我们使用一个defaultdict这样我们就不必手动初始化列表。

把它放在一起:

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> for v, k in enumerate('abc', 1):
...     d[k].append(v)    
...     
>>> d
defaultdict(<class 'list'>, {'a': [1], 'b': [2], 'c': [3]})
>>> d['c'].append(10)
>>> d
defaultdict(<class 'list'>, {'a': [1], 'b': [2], 'c': [3, 10]})

您可以通过创建一个新类来重写更新函数:

在 Pythonbulitins.py中:

def update(self, E=None, **F): # known special case of dict.update
"""
D.update([E, ]**F) -> None.  Update D from dict/iterable E and F.
If E is present and has a .keys() method, then does:  for k in E: D[k] = E[k]
If E is present and lacks a .keys() method, then does:  for k, v in E: D[k] = v
In either case, this is followed by: for k in F:  D[k] = F[k]
"""
pass

所以我写了这个(继承自UserDict,由@timgeb建议(:

from collections import UserDict

class CustomDict(UserDict):
def __init__(self):
super().__init__()
def update(self, E=None, **F) -> None:
if E:
if isinstance(E, dict):
for k in E:
self[k] = E[k]
else:
for k, v in E:
self[k] = v
else:
if isinstance(F, dict):
for key in F:
if isinstance(self[key], list):
self[key].append(F[key])
else:
self[key] = [self[key], F[key]]

dictionary = CustomDict()
dictionary.update({'a': 1, 'b': 2, 'c': 3})
print(dictionary)
dictionary.update(a=3)
print(dictionary)
dictionary.update(a=4)
print(dictionary)

结果:

{'a': 1, 'b': 2, 'c': 3}
{'a': [1, 3], 'b': 2, 'c': 3}
{'a': [1, 3, 4], 'b': 2, 'c': 3}

也许我的代码中有一些逻辑错误,但欢迎指出。

也许你可以使用这样的东西:

dictionary = {'a':1, 'b':2, 'c':3}
dictionary.update({'c': 10 if not dictionary.get('c') else tuple([dictionary['c'],] + [10,])})
# {'a': 1, 'b': 2, 'c': (3, 10)}

但它可能应该包装成一个函数以使事情变得干净。一般模式是(我想,根据您的问题(:

dict = {...}
if 'a' not in dict:
do_this() # just add it to the dict?
else:
do_that() # build a tuple or list?

在你上面的问题中,你混合了类型 - 我不确定你是否想要,一种更pythonic的方法可能是将所有值作为列表并使用defaultdict

最新更新