Hướng dẫn can you flatten a dictionary in python? - bạn có thể làm phẳng một từ điển trong python không?

Có hai cân nhắc lớn mà poster ban đầu cần xem xét:

  1. Có các vấn đề về không gian Keyspace không? Ví dụ, {'a_b':{'c':1}, 'a':{'b_c':2}} sẽ dẫn đến {'a_b_c':???}. Giải pháp dưới đây trốn tránh vấn đề bằng cách trả về một cặp có thể lặp lại.
  2. Nếu hiệu suất là một vấn đề, chức năng Giảm khóa [mà tôi gọi là 'Tham gia'] có yêu cầu truy cập vào toàn bộ đường dẫn khóa hay nó có thể làm O [1] hoạt động ở mọi nút trong cây không? Nếu bạn muốn có thể nói joinedKey = '_'.join[*keys], điều đó sẽ khiến bạn phải trả giá cho thời gian chạy O [N^2]. Tuy nhiên, nếu bạn sẵn sàng nói nextKey = previousKey+'_'+thisKey, điều đó giúp bạn có thời gian o [n]. Giải pháp dưới đây cho phép bạn thực hiện cả hai [vì bạn chỉ có thể kết hợp tất cả các khóa, sau đó xử lý chúng].

. Các nút nhiều lần [điều này khá dễ dàng để vô tình làm], bạn đang thực hiện o [n^2] hoạt động chứ không phải o [n]. Điều này là do có thể bạn đang tính toán khóa ____99 thì

               [k0,k1,...,kN].foldleft[J]
                           /    \
                         ...    kN
                         /
       J[k0,J[k1,J[k2,k3]]]
                       /  \
                      /    \
           J[J[k0,k1],k2]   k3
                    /   \
                   /     \
             J[k0,k1]    k2
                 /  \
                /    \
               k0     k1
0 sau đó ________ 11 ...,, Và sau đó tính toán a sau đó
               [k0,k1,...,kN].foldleft[J]
                           /    \
                         ...    kN
                         /
       J[k0,J[k1,J[k2,k3]]]
                       /  \
                      /    \
           J[J[k0,k1],k2]   k3
                    /   \
                   /     \
             J[k0,k1]    k2
                 /  \
                /    \
               k0     k1
0 sau đó ____ 14 ..., nhưng thực sự bạn không cần phải tính toán lại ____10. tệ như vậy. Một ví dụ điển hình là suy nghĩ về hiệu suất trên
               [k0,k1,...,kN].foldleft[J]
                           /    \
                         ...    kN
                         /
       J[k0,J[k1,J[k2,k3]]]
                       /  \
                      /    \
           J[J[k0,k1],k2]   k3
                    /   \
                   /     \
             J[k0,k1]    k2
                 /  \
                /    \
               k0     k1
6]

Dưới đây là một chức năng tôi đã viết

               [k0,k1,...,kN].foldleft[J]
                           /    \
                         ...    kN
                         /
       J[k0,J[k1,J[k2,k3]]]
                       /  \
                      /    \
           J[J[k0,k1],k2]   k3
                    /   \
                   /     \
             J[k0,k1]    k2
                 /  \
                /    \
               k0     k1
7 có thể thích nghi với nhiều mục đích và có thể làm những gì bạn muốn. Đáng buồn là nó khá khó để tạo ra một phiên bản lười biếng của chức năng này mà không phải chịu các hình phạt hiệu suất ở trên [nhiều python tích hợp như chuỗi.from_iterable không thực sự hiệu quả, điều mà tôi chỉ nhận ra sau khi thử nghiệm rộng rãi ba phiên bản khác nhau của mã này trước khi giải quyết cái này].

from collections import Mapping
from itertools import chain
from operator import add

_FLAG_FIRST = object[]

def flattenDict[d, join=add, lift=lambda x:[x,]]:
    results = []
    def visit[subdict, results, partialKey]:
        for k,v in subdict.items[]:
            newKey = lift[k] if partialKey==_FLAG_FIRST else join[partialKey,lift[k]]
            if isinstance[v,Mapping]:
                visit[v, results, newKey]
            else:
                results.append[[newKey,v]]
    visit[d, results, _FLAG_FIRST]
    return results

Để hiểu rõ hơn những gì đang diễn ra, bên dưới là một sơ đồ cho những người không quen thuộc với ____ 18 [trái], còn được gọi là "Fold trái". Đôi khi nó được vẽ với giá trị ban đầu thay cho K0 [không phải là một phần của danh sách, được chuyển vào hàm]. Ở đây,

               [k0,k1,...,kN].foldleft[J]
                           /    \
                         ...    kN
                         /
       J[k0,J[k1,J[k2,k3]]]
                       /  \
                      /    \
           J[J[k0,k1],k2]   k3
                    /   \
                   /     \
             J[k0,k1]    k2
                 /  \
                /    \
               k0     k1
9 là chức năng
>>> reduce[lambda a,b:[a,b], range[5]]
[[[[0, 1], 2], 3], 4]
0 của chúng tôi. Chúng tôi xử lý trước mỗi kN với
>>> reduce[lambda a,b:[a,b], range[5]]
[[[[0, 1], 2], 3], 4]
1.

               [k0,k1,...,kN].foldleft[J]
                           /    \
                         ...    kN
                         /
       J[k0,J[k1,J[k2,k3]]]
                       /  \
                      /    \
           J[J[k0,k1],k2]   k3
                    /   \
                   /     \
             J[k0,k1]    k2
                 /  \
                /    \
               k0     k1

Điều này trên thực tế giống như

>>> reduce[lambda a,b:[a,b], range[5]]
[[[[0, 1], 2], 3], 4]
2, nhưng trong đó chức năng của chúng tôi thực hiện điều này với tất cả các đường dẫn chính của cây.

>>> reduce[lambda a,b:[a,b], range[5]]
[[[[0, 1], 2], 3], 4]

Trình diễn [mà tôi sẽ đặt vào DocString]:

>>> testData = {
        'a':1,
        'b':2,
        'c':{
            'aa':11,
            'bb':22,
            'cc':{
                'aaa':111
            }
        }
    }
from pprint import pprint as pp

>>> pp[dict[ flattenDict[testData] ]]
{['a',]: 1,
 ['b',]: 2,
 ['c', 'aa']: 11,
 ['c', 'bb']: 22,
 ['c', 'cc', 'aaa']: 111}

>>> pp[dict[ flattenDict[testData, join=lambda a,b:a+'_'+b, lift=lambda x:x] ]]
{'a': 1, 'b': 2, 'c_aa': 11, 'c_bb': 22, 'c_cc_aaa': 111}    

>>> pp[dict[ [v,k] for k,v in flattenDict[testData, lift=hash, join=lambda a,b:hash[[a,b]]] ]]
{1: 12416037344,
 2: 12544037731,
 11: 5470935132935744593,
 22: 4885734186131977315,
 111: 3461911260025554326}

Màn biểu diễn:

from functools import reduce
def makeEvilDict[n]:
    return reduce[lambda acc,x:{x:acc}, [{i:0 for i in range[n]}]+range[n]]

import timeit
def time[runnable]:
    t0 = timeit.default_timer[]
    _ = runnable[]
    t1 = timeit.default_timer[]
    print['took {:.2f} seconds'.format[t1-t0]]

>>> pp[makeEvilDict[8]]
{7: {6: {5: {4: {3: {2: {1: {0: {0: 0,
                                 1: 0,
                                 2: 0,
                                 3: 0,
                                 4: 0,
                                 5: 0,
                                 6: 0,
                                 7: 0}}}}}}}}}

import sys
sys.setrecursionlimit[1000000]

forget = lambda a,b:''

>>> time[lambda: dict[flattenDict[makeEvilDict[10000], join=forget]] ]
took 0.10 seconds
>>> time[lambda: dict[flattenDict[makeEvilDict[100000], join=forget]] ]
[1]    12569 segmentation fault  python

... thở dài, đừng nghĩ rằng một người là lỗi của tôi ...

[Lưu ý lịch sử không quan trọng do các vấn đề điều độ]

Liên quan đến bản sao bị cáo buộc của Flatten một từ điển từ điển [sâu 2 cấp] của danh sách

Giải pháp của câu hỏi đó có thể được thực hiện theo vấn đề này bằng cách thực hiện

>>> reduce[lambda a,b:[a,b], range[5]]
[[[[0, 1], 2], 3], 4]
3. Điều ngược lại là không thể: Mặc dù đúng là các giá trị của
>>> reduce[lambda a,b:[a,b], range[5]]
[[[[0, 1], 2], 3], 4]
4 có thể được phục hồi từ bản sao bị cáo buộc bằng cách ánh xạ một bộ tích lũy bậc cao, người ta không thể khôi phục các khóa. .values of
>>> reduce[lambda a,b:[a,b], range[5]]
[[[[0, 1], 2], 3], 4]
4 can be recovered from the alleged duplicate by mapping a higher-order accumulator, one cannot recover the keys. [edit: Also it turns out that the alleged duplicate owner's question is completely different, in that it only deals with dictionaries exactly 2-level deep, though one of the answers on that page gives a general solution.]

Từ điển trong Python có chưa được giới thiệu không?

Từ điển không được đặt hàng và không nhất thiết phải được lập chỉ mục [trừ khi các khóa là số nguyên 0 - n], nhưng chúng có thể hiểu được [bạn lặp lại các khóa, như ví dụ của bạn cho thấy].can't necessarily be indexed [unless the keys are integers 0 - n ], but they are iterable [you iterate over the keys, as your example shows].

Từ điển có thể được lồng đến bất kỳ độ sâu nào không?

Từ điển có thể được lồng đến bất kỳ độ sâu nào.Một từ điển có thể chứa bất kỳ loại đối tượng nào ngoại trừ từ điển khác.Tất cả các khóa trong từ điển phải cùng loại.. A dictionary can contain any object type except another dictionary. All the keys in a dictionary must be of the same type.

Từ điển có hỗ trợ cắt lát trong Python không?

Cắt từ điển lồng nhau là không thể..

Bài Viết Liên Quan

Chủ Đề