2013-04-30 33 views
9

Tôi có dict sau:Thêm vào một dict sử dụng một danh sách các chuỗi chìa khóa như con đường

aDict = { 
    "a" : { 
     "b" : { 
      "c1" : {}, 
      "c2" : {}, 
     } 
    } 
} 

một dict thứ hai:

aSecondDict = { 
    "d1" : {}, 
    "d2" : {}, 
    "d3" : {}, 
} 

và một "con đường" tuple:

path = ("a", "b", "c2") 

Bây giờ tôi muốn thêm dict thứ hai vào đầu tiên tại đường dẫn được cung cấp bởi bộ dữ liệu:

aResultDict = { 
    "a" : { 
     "b" : { 
      "c1" : {}, 
      "c2" : { 
       "d1" : {}, 
       "d2" : {}, 
       "d3" : {}, 
      }, 
     } 
    } 
} 

Phương pháp pythonic để đạt được điều này là gì?

+1

Ông có thể vui lòng chỉnh sửa từ điển của bạn – jamylak

+0

Cảm ơn Martineau :) –

Trả lời

11

Bạn có thể sử dụng reduce để có được những từ điển và dict.update để đưa những thứ mới trong đó:

reduce(lambda d,key: d[key],path,aDict).update(aSecondDict) 

Bạn thậm chí có thể được một chút thông minh hơn nếu bạn muốn:

reduce(dict.__getitem__,path,aDict).update(aSecondDict) 

Tôi cho rằng cần lưu ý rằng hai phương pháp tiếp cận hơi khác nhau. Các lực lượng thứ hai aDict chỉ chứa nhiều từ điển hơn (hoặc dict lớp con) trong khi trước đây cho phép bất kỳ thứ gì có phương thức __getitem__ ở trong aDict. As noted in the comments, bạn cũng có thể sử dụng:

reduce(dict.get,path,aDict).update(aSecondDict) 

Tuy nhiên, phiên bản này sẽ nâng cao một AttributeError nếu bạn cố gắng đi qua một "liên kết" trong đường dẫn đó là không tồn tại chứ không phải là một KeyError vì vậy tôi không thích nó khá nhiều. Phương thức này cũng thực thi rằng mọi giá trị dọc theo đường dẫn là lớp con dict hoặc dict.

reduce là nội trang dựng sẵn cho python2.x. Bắt đầu từ python2.6 nó cũng có sẵn như functools.reduce. Mã mà muốn trở thành tương thích với python3.x nên cố gắng sử dụng functools.reduce như BUILTIN được lấy ra trong python3.x

+0

hoặc 'giảm ​​(dict.get, đường dẫn, d) ' – jamylak

+0

@jamylak - Phải. Trình khởi tạo luôn đi cuối cùng. Cảm ơn. – mgilson

+1

Ngoài ra nếu OP muốn có một bản sao, anh ta chỉ có thể sử dụng 'copy.deepcopy' và sau đó làm điều này – jamylak

Các vấn đề liên quan