शब्दकोश: कैसे हर कुंजी रास्ता है कि एक निश्चित मान सूची?

वोट
2

कहते हैं कि मैं फार्म का एक शब्दकोश मिल गया है की सुविधा देता है:

d={'geo': {'bgcolor': 'white','lakecolor': 'white','caxis': {'gridcolor': 'white', 'linecolor': 'white',}},
    'title': {'x': 0.05},
    'yaxis': {'automargin': True,'linecolor': 'white','ticks': '','zerolinecolor': 'white','zerolinewidth': 2}
  }

कैसे आपको लगता है कि dict के माध्यम से अपने तरीके से काम और प्रत्येक पूरा कुंजी रास्ता है कि मान की एक सूची बना सकते हैं 'white'? एक समारोह में पद उपयोगकर्ता JFS द्वारा परिभाषित का उपयोग करते हुए एक नेस्टेड शब्दकोश अजगर में एक मूल्य के लिए खोज आप या नहीं, जांच की सुविधा देता है 'white'कम से कम एक समय होता है और यह भी पथ देता है:

# in:
def getpath(nested_dict, value, prepath=()):
    for k, v in nested_dict.items():
        path = prepath + (k,)
        if v == value: # found value
            return path
        elif hasattr(v, 'items'): # v is a dict
            p = getpath(v, value, path) # recursive call
            if p is not None:
                return p
getpath(d,'white')

# out:
('geo', 'bgcolor')

लेकिन 'सफेद' अन्य स्थानों में भी, में की तरह होती है:

1। d['geo']['lakecolor']

2: d['geo']['caxis']['gridcolor']

3: d['yaxis']['linecolor']

मुझे यकीन है कि समारोह सभी रास्ते पाता है कैसे कर सकते हैं?

मैं जब तक यह रिटर्न ऊपर समारोह को लागू करने की कोशिश की है noneएक एक करके पाया रास्तों को समाप्त करते हुए, लेकिन वह जल्दी से एक बदसूरत गंदगी में बदल गया।

किसी भी सुझाव के लिए आपका धन्यवाद!

02/12/2019 को 23:54
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


3 जवाब

वोट
1

रिटर्निंग क्या परिणाम अधूरा बना देता है। इसके बजाय लौटने का, अपने पथ को ट्रैक करने के लिए एक अलग सूची का उपयोग करें। मैं इस सूची का उपयोग कर रहा cur_listयहाँ, और लूप के अंत में यह लौटने:

d = {
  'geo': {'bgcolor': 'white',
         'caxis': {'gridcolor': 'white', 'linecolor': 'white'},
         'lakecolor': 'white'},
  'title': {'x': 0.05},
  'yaxis': {'automargin': True,
           'linecolor': 'white',
           'ticks': '',
           'zerolinecolor': 'white',
           'zerolinewidth': 2}
}

cur_list = []

def getpath(nested_dict, value, prepath=()):
    for k, v in nested_dict.items():
        path = prepath + (k,)
        if v == value: # found value
            cur_list.append(path)
        elif isinstance(v, dict): # v is a dict
            p = getpath(v, value, path, cur_list) # recursive call
            if p is not None:
                cur_list.append(p)

getpath(d,'white')
print(cur_list)


# RESULT:
# [('geo', 'bgcolor'), ('geo', 'caxis', 'gridcolor'), ('geo', 'caxis', 'linecolor'), ('geo', 'lakecolor'), ('yaxis', 'linecolor'), ('yaxis', 'zerolinecolor')]
03/12/2019 को 00:00
का स्रोत उपयोगकर्ता

वोट
1

सिर्फ इसलिए यह एक रिटर्न अपने कार्य को बदलने listऔर नहीं है returnजब कुछ पाया जाता है। बस / सूची का विस्तार करने के लिए जोड़

def getpath(nested_dict, value, prepath=()):
    p = []
    for k, v in nested_dict.items():
        path = prepath + (k,)
        if v == value: # found value
            p.append(path)
        elif hasattr(v, 'items'): # v is a dict
            p += getpath(v, value, path) # recursive call
    return p

अपने इनपुट डेटा के साथ, यह पैदा करता है (क्रम अजगर संस्करण के आधार पर भिन्न हो सकते हैं जहां शब्दकोशों अव्यवस्थित हैं):

[('yaxis', 'linecolor'), ('yaxis', 'zerolinecolor'), ('geo', 'lakecolor'), 
('geo', 'caxis', 'linecolor'), ('geo', 'caxis', 'gridcolor'), ('geo', 'bgcolor')]
03/12/2019 को 00:00
का स्रोत उपयोगकर्ता

वोट
5

यह एक आदर्श उपयोग के मामले में जनरेटर लिखने के लिए है:

def find_paths(haystack, needle):
    if haystack == needle:
        yield ()
    if not isinstance(haystack, dict):
        return
    for key, val in haystack.items():
        for subpath in find_paths(val, needle):
            yield (key, *subpath)

इस प्रकार आप इसका इस्तेमाल कर सकते हैं:

d = {
    'geo': {'bgcolor': 'white','lakecolor': 'white','caxis': {'gridcolor': 'white', 'linecolor': 'white',}},
    'title': {'x': 0.05},
    'yaxis': {'automargin': True,'linecolor': 'white','ticks': '','zerolinecolor': 'white','zerolinewidth': 2}
}

# you can iterate over the paths directly...
for path in find_paths(d, 'white'):
    print('found at path: ', path)

# ...or you can collect them into a list:
paths = list(find_paths(d, 'white'))
print('found at paths: ' + repr(paths))

जनरेटर दृष्टिकोण लाभ यह एक बार में स्मृति में सभी रास्तों को रखने के लिए एक वस्तु बनाने की जरूरत नहीं है कि है; वे एक के बाद एक संसाधित किया जा सकता है और तुरंत खारिज कर दिया। इस मामले में, स्मृति बचत बल्कि मामूली होगा, लेकिन अन्य लोगों में वे महत्वपूर्ण हो सकता है। इसके अलावा, अगर एक जनरेटर पर एक पाश-बार दोहराना जल्दी समाप्त हो जाता है, जनरेटर नहीं अधिक रास्तों कि बाद में वैसे भी खारिज कर दिया हो जाएगा के लिए खोज रखने के लिए जा रहा है।

03/12/2019 को 00:18
का स्रोत उपयोगकर्ता

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more