2015-10-04 18 views
8

Tôi có một bộ tùy tiện sâu của từ điển lồng nhau:Python: Áp dụng chức năng để giá trị trong từ điển lồng nhau

x = {'a': 1, 'b': {'c': 6, 'd': 7, 'g': {'h': 3, 'i': 9}}, 'e': {'f': 3}} 

và tôi muốn về cơ bản áp dụng một chức năng để tất cả các số nguyên trong từ điển, vì vậy như map , Tôi đoán, nhưng đối với các từ điển lồng nhau.

Vì vậy: map_nested_dicts(x, lambda v: v + 7) sẽ là loại mục tiêu.

Tôi bị kẹt là cách tốt nhất để lưu trữ các lớp khóa sau đó đặt giá trị được sửa đổi trở lại vị trí chính xác của nó.

Cách tốt nhất/cách tiếp cận để thực hiện việc này là gì?

+0

Một giải pháp đệ quy mig ht làm việc. Lặp lại các mục, nếu một giá trị là một số nguyên, thay đổi nó, nếu giá trị là một từ điển, chuyển nó trong một cuộc gọi đệ quy. – wwii

Trả lời

13

thăm tất cả các giá trị lồng nhau một cách đệ quy:

import collections 

def map_nested_dicts(ob, func): 
    if isinstance(ob, collections.Mapping): 
     return {k: map_nested_dicts(v, func) for k, v in ob.iteritems()} 
    else: 
     return func(ob) 

map_nested_dicts(x, lambda v: v + 7) 
# Creates a new dict object: 
# {'a': 8, 'b': {'c': 13, 'g': {'h': 10, 'i': 16}, 'd': 14}, 'e': {'f': 10}} 

Trong một số trường hợp nó mong muốn sửa đổi đối tượng dict gốc (để tránh tái tạo nó):

import collections 

def map_nested_dicts_modify(ob, func): 
    for k, v in ob.iteritems(): 
     if isinstance(v, collections.Mapping): 
      map_nested_dicts_modify(v, func) 
     else: 
      ob[k] = func(v) 

map_nested_dicts_modify(x, lambda v: v + 7) 
# x is now 
# {'a': 8, 'b': {'c': 13, 'g': {'h': 10, 'i': 16}, 'd': 14}, 'e': {'f': 10}} 

Nếu bạn sử dụng Python 3:

  • thay thế.210 với dict.items

  • thay import collections với import collections.abc

  • thay collections.Mapping với collections.abc.Mapping

+0

Tôi đã tự hỏi nếu phương thức '' 'items''' trong hàm đầu tiên có thể gây ra rắc rối nhưng có vẻ như chỉ ánh xạ hoặc các dẫn xuất ánh xạ sử dụng phương thức này - bất kỳ suy nghĩ nào? – wwii

+0

@wwii Đây là một số loại gõ vịt ... Có, nó sẽ làm việc cho 'dict's,' dict' subclasses, 'ChainMap' và nhiều loại ánh xạ. – vaultah

+0

@wwii nhưng có lẽ bạn đã đúng, tôi đã thay thế khối 'try..except' bằng' isinstance (ob, collections.Mapping) 'check. – vaultah

1

Chỉ cần mở rộng về câu trả lời vaultah, nếu một trong những yếu tố có thể là một danh sách, và bạn muốn để xử lý chúng:

import collections 

def map_nested_dicts_modify(ob, func): 
for k, v in ob.iteritems(): 
    if isinstance(v, collections.Mapping): 
     map_nested_dicts_modify(v, func) 
    elif isinstance(v, list): 
     ob[k] = map(func, v) 
    else: 
     ob[k] = func(v) 
Các vấn đề liên quan