Hướng dẫn python recursively flatten dictionary - python đệ quy làm phẳng từ điển

Nghĩ rằng tôi đã có một giải pháp đơn giản cho vấn đề này nhưng hóa ra tôi đã tắt.

Show

Tôi có một từ điển lồng nhau:

my_dict = { "username": "",
  "name": { "first": "John", "last": "Doe" },
  "occupation": "Web Developer" }

Tôi đã viết một chức năng đệ quy để tháo nó vào một từ điển hiện có:

def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)

Bước qua vòng lặp, mọi thứ diễn ra tốt đẹp cho đến khi tôi đạt được đệ quy, sau đó

def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)
0 đi từ từ điển đến
def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)
1.

Tôi không thấy bất kỳ lỗi rõ ràng nào, mặc dù dường như

def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)
2 phá vỡ mọi thứ (và kết thúc vòng lặp). Bất kỳ ý tưởng?

Hướng dẫn python recursively flatten dictionary - python đệ quy làm phẳng từ điển

Trong bài đăng này, chúng tôi sẽ xem xét 4 cách khác nhau để làm phẳng một dict trong Python. Đối với mỗi phương pháp, tôi sẽ chỉ ra những ưu và nhược điểm, và tôi sẽ phân tích hiệu suất nhanh. Đối với hướng dẫn này, tôi đã chạy tất cả các ví dụ về Python 3.7.pros and cons, and I'll give a quick performance analysis. For this tutorial, I ran all examples on Python 3.7.

Tại sao bạn nên biết làm thế nào để làm phẳng một dict trong Python?

Có nhiều lý do bạn sẽ cần một từ điển phẳng. Một là nó làm cho nó đơn giản hơn để so sánh hai dicts. Một điều khác là nó dễ dàng hơn để điều hướng và điều khiển nó, vì một cấu trúc phẳng là một cấp sâu.

Python là một ngôn ngữ đa năng, có nghĩa là bạn có thể đạt được các mục tiêu tương tự theo nhiều cách. Chọn giải pháp tốt nhất cho một vấn đề đòi hỏi trọng số lợi ích của một giải pháp so với một giải pháp khác.

Mục tiêu của bài đăng này là cung cấp cho bạn nhiều tùy chọn cho vấn đề này và cung cấp cho bạn càng nhiều dữ liệu càng tốt để bạn có thể đưa ra quyết định sáng suốt. Vì vậy, hãy để đi.

Tái bút: Nếu bạn không có Python 3.7, bạn có thể cài đặt nó bằng

def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)
3 và thậm chí có nhiều phiên bản cùng một lúc mà không có xung đột.

Mục lục

  1. Sử dụng chức năng đệ quy của riêng bạn
  2. Sử dụng chức năng đệ quy của riêng bạn + Trình tạo
  3. Sử dụng gấu trúc
    def adder(my_dict, existing_dict):
        for k, v in my_dict:
            if not isinstance(v, dict):
                existing_dict[k] = v
            else:
                adder(v.iteritems(), existing_dict)
        return existing_dict
    
    
    existing_dict = { "role": "employee" }
    adder(my_dict.iteritems(), existing_dict)
    
    4
  4. Sử dụng thư viện
    def adder(my_dict, existing_dict):
        for k, v in my_dict:
            if not isinstance(v, dict):
                existing_dict[k] = v
            else:
                adder(v.iteritems(), existing_dict)
        return existing_dict
    
    
    existing_dict = { "role": "employee" }
    adder(my_dict.iteritems(), existing_dict)
    
    5
  5. Sự kết luận

Làm thế nào để làm phẳng một dict trong python bằng cách sử dụng chức năng đệ quy của riêng bạn

Một cái nhìn nhanh về Google dẫn chúng ta đến Stackoverflow. Câu trả lời đầu tiên cho thấy một hàm đệ quy đi qua từ điển và trả về một thể hiện phẳng. Tôi sẽ lấy cảm hứng từ chức năng đó và hiển thị một phiên bản được cải thiện một chút.

Chúng ta có thể bắt đầu bằng cách loại gợi ý nó để cải thiện khả năng đọc và làm cho nó an toàn.

from collections.abc import MutableMapping

def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}

Điểm chuẩn hiệu suất

Chúng tôi đã nhanh chóng xác minh rằng chức năng trả về một chế độ phẳng, nhưng còn hiệu suất của nó thì sao? Nó có tốt cho việc sử dụng sản xuất không? Hãy chạy một điểm chuẩn nhanh để xem nó nhanh như thế nào.

Đối với điều này và tất cả các điểm chuẩn trong bài viết này, tôi sẽ sử dụng hàm ma thuật ____ của ____ 16 và

def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)
8 từ thư viện
def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)
9.

Tái bút: Để

from collections.abc import MutableMapping

def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}
0 hoạt động, bạn cần chạy
from collections.abc import MutableMapping

def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}
1 trước.

In [4]: %timeit flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
7.28 µs ± 54.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [5]: %load_ext memory_profiler

In [6]: %memit flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
peak memory: 84.94 MiB, increment: 0.29 MiB

Ưu điểm: Dễ hiểu, và nó chỉ hoạt động. Easy to understand, and it just works.

Nhược điểm: Nó lưu trữ các mục trong danh sách trong bộ nhớ sau đó được chuyển đến hàm tạo

from collections.abc import MutableMapping

def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}
2. Điều này là lãng phí không chỉ về bộ nhớ mà còn cả tốc độ. It stores the items in a list in memory that is then passed to the
from collections.abc import MutableMapping

def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}
2 constructor. This is wasteful not only in terms of memory but also speed.

Mặc dù việc thêm các yếu tố vào một danh sách trong Python rất nhanh, nhưng việc không thực sự cần thiết. Trong phần tiếp theo, chúng ta sẽ xem cách cải thiện điều này bằng cách sử dụng máy phát điện.

Cách làm phẳng một dict trong Python bằng cách sử dụng hàm đệ quy của riêng bạn + máy phát điện

Phiên bản đầu tiên hoạt động và nó hơi nhanh. Tuy nhiên, nó có một vấn đề.

Để tạo một từ điển mới với các phím phẳng, nó sẽ duy trì trong bộ nhớ một con trăn

from collections.abc import MutableMapping

def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}
3. Điều này là không hiệu quả, vì chúng ta phải giữ toàn bộ cấu trúc dữ liệu trong bộ nhớ chỉ để phục vụ như một bộ lưu trữ tạm thời.

Một giải pháp tốt hơn nhiều là sử dụng các trình tạo của Python, một đối tượng có thể tạm dừng thực thi và nhớ trạng thái có thể được nối lại sau. Bằng cách sử dụng một trình tạo, chúng ta có thể thoát khỏi danh sách tạm thời mà không có thay đổi trong hành vi.

from collections.abc import MutableMapping

def _flatten_dict_gen(d, parent_key, sep):
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            yield from flatten_dict(v, new_key, sep=sep).items()
        else:
            yield new_key, v


def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str = '.'):
    return dict(_flatten_dict_gen(d, parent_key, sep))

>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}

Điểm chuẩn hiệu suất

Chúng tôi đã nhanh chóng xác minh rằng chức năng trả về một chế độ phẳng, nhưng còn hiệu suất của nó thì sao? Nó có tốt cho việc sử dụng sản xuất không? Hãy chạy một điểm chuẩn nhanh để xem nó nhanh như thế nào.

Đối với điều này và tất cả các điểm chuẩn trong bài viết này, tôi sẽ sử dụng hàm ma thuật ____ của ____ 16 và

def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)
8 từ thư viện
def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)
9.
Easy to understand, it works like the previous version, and it's memory efficient. This version consumes about 50% less memory than the version using lists.

Tái bút: Để

from collections.abc import MutableMapping

def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}
0 hoạt động, bạn cần chạy
from collections.abc import MutableMapping

def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}
1 trước.
It might not handle edge cases very well. For example if we pass a dictionary-like object that is not an instance of
from collections.abc import MutableMapping

def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}
4 then this example will fail. But this is a disadvantage of the previous version as well.

Ưu điểm: Dễ hiểu, và nó chỉ hoạt động.

Nhược điểm: Nó lưu trữ các mục trong danh sách trong bộ nhớ sau đó được chuyển đến hàm tạo

from collections.abc import MutableMapping

def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}
2. Điều này là lãng phí không chỉ về bộ nhớ mà còn cả tốc độ.

Mặc dù việc thêm các yếu tố vào một danh sách trong Python rất nhanh, nhưng việc không thực sự cần thiết. Trong phần tiếp theo, chúng ta sẽ xem cách cải thiện điều này bằng cách sử dụng máy phát điện.

Cách làm phẳng một dict trong Python bằng cách sử dụng hàm đệ quy của riêng bạn + máy phát điện

from collections.abc import MutableMapping
import pandas as pd

def flatten_dict(d: MutableMapping, sep: str= '.') -> MutableMapping:
    [flat_dict] = pd.json_normalize(d, sep=sep).to_dict(orient='records')
    return flat_dict


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'd': [6, 7, 8], 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5}

Điểm chuẩn hiệu suất

In [5]: %timeit flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
779 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [6]: %memit flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
peak memory: 86.30 MiB, increment: 0.90 MiB

Chúng tôi đã nhanh chóng xác minh rằng chức năng trả về một chế độ phẳng, nhưng còn hiệu suất của nó thì sao? Nó có tốt cho việc sử dụng sản xuất không? Hãy chạy một điểm chuẩn nhanh để xem nó nhanh như thế nào. Easy to understand, and we reuse a well-established library.

Đối với điều này và tất cả các điểm chuẩn trong bài viết này, tôi sẽ sử dụng hàm ma thuật ____ của ____ 16 và

def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)
8 từ thư viện
def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)
9.
Using
from collections.abc import MutableMapping

def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}
6 just to flatten a dict seems like overkill. If your project doesn't need it, then we can use a more lightweight library such as
from collections.abc import MutableMapping

def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}
9. Besides, according to
def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)
7 this version is 100x slower than using our own solution, which is not great.

Tái bút: Để from collections.abc import MutableMapping def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping: items = [] for k, v in d.items(): new_key = parent_key + sep + k if parent_key else k if isinstance(v, MutableMapping): items.extend(flatten_dict(v, new_key, sep=sep).items()) else: items.append((new_key, v)) return dict(items) >>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]}) {'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]} 0 hoạt động, bạn cần chạy from collections.abc import MutableMapping def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping: items = [] for k, v in d.items(): new_key = parent_key + sep + k if parent_key else k if isinstance(v, MutableMapping): items.extend(flatten_dict(v, new_key, sep=sep).items()) else: items.append((new_key, v)) return dict(items) >>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]}) {'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]} 1 trước.

Ưu điểm: Dễ hiểu, và nó chỉ hoạt động.

Nhược điểm: Nó lưu trữ các mục trong danh sách trong bộ nhớ sau đó được chuyển đến hàm tạo

from collections.abc import MutableMapping

def flatten_dict(d: MutableMapping, parent_key: str = '', sep: str ='.') -> MutableMapping:
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, MutableMapping):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


>>> flatten_dict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]})
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}
2. Điều này là lãng phí không chỉ về bộ nhớ mà còn cả tốc độ.

Thay vào đó, chúng ta có thể sử dụng

def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)
5, nhẹ hơn nhiều và được thử nghiệm chiến đấu.

Thư viện rất linh hoạt và cũng cho phép chúng tôi sử dụng các bộ phân cách tùy chỉnh. Tuy nhiên, một trong những tính năng tốt nhất mà nó cung cấp là khả năng truy cập từ điển mới được tạo như trước đây - nghĩa là, bạn có thể truy cập các giá trị bằng cách sử dụng các khóa mới hoặc các khóa cũ.

Hãy xem một ví dụ.

>>> import flatdict
>>> d =  flatdict.FlatDict(data, delimiter='.')

# d is a FlatDict instance
>>> d
"

# and it allows accessing flat keys
>>> d['c.b.y']
4

# but also nested ones
>>> d['c']['b']['y']
4

# and can be converted to a flatten dict
>>> dict(d)
{'a': 1, 'c.a': 2, 'c.b.x': 3, 'c.b.y': 4, 'c.b.z': 5, 'd': [6, 7, 8]}

Như bạn có thể thấy,

def adder(my_dict, existing_dict):
    for k, v in my_dict:
        if not isinstance(v, dict):
            existing_dict[k] = v
        else:
            adder(v.iteritems(), existing_dict)
    return existing_dict


existing_dict = { "role": "employee" }
adder(my_dict.iteritems(), existing_dict)
5 cho phép sự linh hoạt và thuận tiện tuyệt vời.

Điểm chuẩn hiệu suất

In [3]: %timeit flatdict.FlatDict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]}, delimiter='.')
8.97 µs ± 21.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [4]: %memit flatdict.FlatDict({'a': 1, 'c': {'a': 2, 'b': {'x': 3, 'y': 4, 'z': 5}}, 'd': [6, 7, 8]}, delimiter='.')
peak memory: 45.21 MiB, increment: 0.14 MiB

Ưu điểm: dễ hiểu, và nó chỉ hoạt động, và đó là một thư viện nhẹ. Cho phép truy cập các yếu tố lồng nhau theo hai cách khác nhau. Cũng nhanh và bộ nhớ hiệu quả như giải pháp sử dụng máy phát điện. Easy to understand, and it just works, and it's a lightweight library. Allows accessing nested elements in two different ways. Just as fast and memory efficient as the solution using generators.

Nhược điểm: Nó vẫn là một thư viện bên ngoài và giống như nhiều công cụ nguồn mở, nếu có lỗi bạn cần đợi tác giả sửa nó. Và đôi khi các tác giả từ bỏ các dự án của họ, trong đó giới thiệu rủi ro cho dự án của bạn. Bất kể, tôi vẫn nghĩ rằng những ưu điểm lớn hơn các nhược điểm trong trường hợp này. It is still an external library, and like many open-source tools, if there's a bug you need to wait for the author to fix it. And sometimes authors abandon their projects, which introduces risk to your project. Regardless, I still think the pros outweigh the cons in this case.

Sự kết luận

Trong bài đăng này, chúng tôi đã thấy 4 cách khác nhau để làm phẳng một từ điển trong Python. Mỗi giải pháp đi kèm với ưu và nhược điểm, và chọn một giải pháp tốt nhất là vấn đề của sở thích cá nhân và hạn chế dự án.

Tôi hy vọng bạn thích nó và gặp bạn lần sau!



Học mã miễn phí. Chương trình giảng dạy nguồn mở của Freecodecamp đã giúp hơn 40.000 người có được việc làm với tư cách là nhà phát triển. Bắt đầu