d3 = dict(d1, **d2)
Tôi hiểu rằng điều này hợp nhất từ điển. Nhưng, nó có phải là duy nhất? Điều gì sẽ xảy ra nếu d1 có cùng khóa với d2 nhưng khác giá trị? Tôi muốn d1 và d2 được hợp nhất, nhưng d1 được ưu tiên nếu có khóa trùng lặp.
d3 = dict(d1, **d2)
Tôi hiểu rằng điều này hợp nhất từ điển. Nhưng, nó có phải là duy nhất? Điều gì sẽ xảy ra nếu d1 có cùng khóa với d2 nhưng khác giá trị? Tôi muốn d1 và d2 được hợp nhất, nhưng d1 được ưu tiên nếu có khóa trùng lặp.
Câu trả lời:
Bạn có thể sử dụng .update()
phương pháp này nếu không cần bản gốc d2
nữa:
Cập nhật từ điển bằng các cặp khóa / giá trị từ các khóa khác, ghi đè các khóa hiện có . Trở lại
None
.
Ví dụ:
>>> d1 = {'a': 1, 'b': 2}
>>> d2 = {'b': 1, 'c': 3}
>>> d2.update(d1)
>>> d2
{'a': 1, 'c': 3, 'b': 2}
Cập nhật:
Tất nhiên, bạn có thể sao chép từ điển trước để tạo một từ điển mới được hợp nhất. Điều này có thể cần thiết hoặc không. Trong trường hợp bạn có các đối tượng ghép (các đối tượng chứa các đối tượng khác, như danh sách hoặc cá thể lớp) trong từ điển của mình, copy.deepcopy
cũng nên được xem xét.
isinstance(int, object) is True
nhưng deepcopy
dường như không cần thiết.
Trong Python2,
d1={'a':1,'b':2}
d2={'a':10,'c':3}
d1 ghi đè d2:
dict(d2,**d1)
# {'a': 1, 'c': 3, 'b': 2}
d2 ghi đè d1:
dict(d1,**d2)
# {'a': 10, 'c': 3, 'b': 2}
Hành vi này không chỉ là một sự may mắn khi thực hiện; nó được đảm bảo trong tài liệu :
Nếu một khóa được chỉ định cả trong đối số vị trí và đối số từ khóa, thì giá trị được liên kết với từ khóa sẽ được giữ lại trong từ điển.
**
ký hiệu, tất cả các khóa của lệnh đó phải là chuỗi. Xem chuỗi python-dev bắt đầu tại mail.python.org/pipermail/python-dev/2010-April/099427.html để biết thêm.
d = dict(**d1, **d2)
quả, nhưng đó là những gì @IoannisFilippidis tham chiếu trong nhận xét của họ. Có lẽ bao gồm đoạn mã ở đây sẽ rõ ràng hơn, vì vậy nó là ở đây.
Giải pháp của tôi là xác định một hàm hợp nhất . Nó không phức tạp và chỉ tốn một đường. Đây là mã trong Python 3.
from functools import reduce
from operator import or_
def merge(*dicts):
return { k: reduce(lambda d, x: x.get(k, d), dicts, None) for k in reduce(or_, map(lambda x: x.keys(), dicts), set()) }
Kiểm tra
>>> d = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> d_letters = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d, d_letters)
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d_letters, d)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> merge(d_letters)
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge()
{}
Nó hoạt động với số lượng đối số từ điển tùy ý. Nếu có bất kỳ khóa trùng lặp nào trong từ điển đó, khóa từ từ điển ngoài cùng bên phải trong danh sách đối số sẽ thắng.
.update
cuộc gọi trong đó ( merged={}
theo sau là for d in dict: merged.update(d)
) sẽ ngắn hơn, dễ đọc hơn và hiệu quả hơn.
reduce
và lambda
s, làm thế nào về return reduce(lambda x, y: x.update(y) or x, dicts, {})
?
Trey Hunner có một bài đăng trên blog rất hay, phác thảo một số tùy chọn để hợp nhất nhiều từ điển, bao gồm (dành cho python3.3 +) ChainMap và giải nén từ điển .
Bắt đầu từ Python 3.9
, toán tử |
tạo một từ điển mới với các khóa và giá trị được hợp nhất từ hai từ điển:
# d1 = { 'a': 1, 'b': 2 }
# d2 = { 'b': 1, 'c': 3 }
d3 = d2 | d1
# d3: {'b': 2, 'c': 3, 'a': 1}
Điều này:
Tạo một từ điển mới d3 với các khóa và giá trị được hợp nhất của d2 và d1. Các giá trị của d1 được ưu tiên khi d2 và d1 dùng chung khóa.
Cũng lưu ý |=
toán tử sửa đổi d2 bằng cách hợp nhất d1 vào, với mức độ ưu tiên trên các giá trị d1:
# d1 = { 'a': 1, 'b': 2 }
# d2 = { 'b': 1, 'c': 3 }
d2 |= d1
# d2: {'b': 2, 'c': 3, 'a': 1}
Tôi tin rằng, như đã nói ở trên, sử dụng d2.update(d1)
là cách tốt nhất và bạn cũng có thể sao chép d2
trước nếu vẫn cần.
Mặc dù, tôi muốn chỉ ra rằng đó dict(d1, **d2)
thực sự là một cách không tốt để hợp nhất các thứ nguyên nói chung vì các đối số của từ khóa cần phải là chuỗi, do đó, nó sẽ không thành công nếu bạn có dict
như sau:
{
1: 'foo',
2: 'bar'
}
**
truyền đối số từ khóa trừ khi tất cả các khóa củad2
đều là chuỗi. Nếu không phải tất cả các khóa củad2
đều là chuỗi, điều này không thành công trong Python 3.2 và trong các triển khai thay thế của Python như Jython, IronPython và PyPy. Ví dụ: xem mail.python.org/pipermail/python-dev/2010-April/099459.html .