假設我有一個充滿嵌套值的大字典,例如:
large_dic ={
...
"key":{"sub-key1" :{"sub-key2": "Test"}},
"0key":{"0sub-key1": "0Test"},
"1key":{"1sub-key1":{"1sub-key2":{"1sub-key3":"1Test"}}}
...
}
我想做的是能夠從最終值中獲得例如:
"1Test"
訪問它的密鑰,例如在這種情況下:
large_dic["1key"]["1sub-key1"]["1sub-key2"]["1sub-key3"]
感謝您的支持。
編輯以添加更多資訊:我正在談論的字典樹是線性的(YAML 檔案轉換為 python 字典結構),永遠不會超過一個鍵,結束葉值可能不是唯一的。
uj5u.com熱心網友回復:
由于 OP 正在尋找分層鍵,而不是
我創建了這個類:
class PointingSlice:
def __init__(self, obj, *slices) -> None:
self.obj = obj
self.slices = slices
def __str__(self):
return f"{str(self.obj)}{''.join(map(self._repr_slice, self.slices))}"
def _repr_slice(self, sliced: slice):
sqbrackets = "[{}]"
if not isinstance(sliced, slice):
return sqbrackets.format(repr(sliced))
items = [sliced.start, sliced.stop, sliced.step]
fn = lambda x: str() if x is None else str(x)
return sqbrackets.format(":".join(map(fn, items)))
def resolve(self):
obj = self.obj
for sliced in self.slices:
obj = obj.__getitem__(sliced)
return obj
這個函式用于實體化:
def find_longest(mapping, key):
keys = [key]
value = mapping[key]
while isinstance(value, dict):
((k, value),) = value.items()
keys.append(k)
return PointingSlice(mapping, *keys)
示例使用:
print(find_longest(large_dic, "1key"))
# output:
# {'key': {'sub-key1': {'sub-key2': 'Test'}}, '0key': {'0sub-key1': '0Test'}, '1key': {'1sub-key1': {'1sub-key2': {'1sub-key3': '1Test'}}}}['1key']['1sub-key1']['1sub-key2']['1sub-key3']
# do note that it is the same thing as large_dic['1key']['1sub-key1']['1sub-key2']['1sub-key3']
print(find_longest(large_dic, "1key").resolve()) # 1Test
所以我做了一些更改,現在它支持與您的確切用例匹配的其他 repr 選項:
class PointingSlice:
def __init__(self, obj, *slices, object_name=None) -> None:
self.obj = obj
self.slices = slices
self.object_name = object_name
def __str__(self):
return f"{self.object_name or str(self.obj)}{''.join(map(self._repr_slice, self.slices))}"
def _repr_slice(self, sliced: slice):
sqbrackets = "[{}]"
if not isinstance(sliced, slice):
return sqbrackets.format(repr(sliced))
items = [sliced.start, sliced.stop, sliced.step]
fn = lambda x: str() if x is None else str(x)
return sqbrackets.format(":".join(map(fn, items)))
def resolve(self):
obj = self.obj
for sliced in self.slices:
obj = obj.__getitem__(sliced)
return obj
large_dic = {
"key": {"sub-key1": {"sub-key2": "Test"}},
"0key": {"0sub-key1": "0Test"},
"1key": {"1sub-key1": {"1sub-key2": {"1sub-key3": "1Test"}}},
}
def find_longest(mapping, key):
keys = [key]
value = mapping[key]
while isinstance(value, dict):
((k, value),) = value.items()
keys.append(k)
return PointingSlice(mapping, *keys)
f = find_longest(large_dic, "1key")
f.object_name = "large_dic" # for representational purposes, it works without this
print(f) # large_dic['1key']['1sub-key1']['1sub-key2']['1sub-key3']
print(f.resolve()) # 1Test
uj5u.com熱心網友回復:
是的,這完全有可能。這是獲取深度嵌套值的函式:
def get_final_value(mapping, key):
value = mapping[key]
while isinstance(value, dict):
(value,) = value.values()
return value
示例使用:
>>> get_final_value(large_dic, "key")
'Test'
>>> get_final_value(large_dic, "0key")
'0Test'
>>> get_final_value(large_dic, "1key")
'1Test'
>>>
uj5u.com熱心網友回復:
有很多方法可以實作這一目標。您可能想查找“前綴樹遍歷”(或“trie 遍歷”)。
記憶體效率低的簡單遞回解決方案可能如下所示:
def find_trie_leaf_path(trie: dict, leaf_value, trie_path: list[str] = []):
for key, value in trie.items():
if isinstance(value, dict):
yield from find_trie_leaf_path(value, leaf_value, trie_path [key])
elif value == leaf_value:
yield trie_path [key]
large_dic = {
"key": {"sub-key1": {"sub-key2": "Test"}},
"0key": {"0sub-key1": "0Test"},
"1key": {"1sub-key1": {"1sub-key2": {"1sub-key3": "Test"}}},
}
first_match = next(find_trie_leaf_path(large_dic, "Test"))
all_matches = list(find_trie_leaf_path(large_dic, "Test"))
即使您的嘗試非常廣泛,這也應該有效。如果它非常高,我寧愿使用迭代演算法。
不過,我想指出的是,前綴樹通常以相反的方式使用。如果您發現自己非常需要此搜索,則應考慮使用不同的資料結構。
uj5u.com熱心網友回復:
可以以任何方式從您的最終值中推斷出父鍵,還是樹結構相當隨機?如果是后者,那么您可能最終會搜索您的樹,直到找到您的value,您為此選擇的路徑搜索演算法再次取決于您擁有的樹結構。正如評論中已經詢問的那樣,每個節點是否只有一個其他節點或者它是二進制的還是可以有許多子節點?
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/517015.html
