我有一個物件串列。這些物件具有嵌套屬性,這些屬性是根據 hpaulj 在這篇文章中的回應生成的:嵌套字典的類物件屬性訪問。
我希望能夠在這些物件中找到屬性和屬性值,并操作它們持有的資料。然而,在實際場景中,可能有超過一百萬個物件,并且屬性可能是深度嵌套的,這使得在需要進行大量操作時通過平面串列進行搜索是一項代價高昂的練習。
例如,假設物件串列如下:
list_of_objects = [object1, object2, object3, object4]
- object1 具有以下屬性:
self.country = "Kenya", self.disease = "breast cancer" - object2 具有以下屬性:
self.country = "Kenya", self.disease = "diabetes" - object3 具有以下屬性:
self.country = 'Ireland', self.risk_factor.smoking = "Current" - object4 具有以下屬性:
self.country = 'Kenya', self.risk_factor.smoking = "Previous"
這些物件是從以下State類創建的:
class State:
def __init__(self, state_dictionary):
self._state_dictionary = state_dictionary
for key, value in self._state_dictionary.items():
if isinstance(value, dict):
value = State(value)
setattr(self, key, value)
在 object3 的情況下,示例state_dictionary如下:
state_dictionary = {
"country":"Ireland",
"risk_factor":{
"smoking":"Current"
}
}
重要的是,嵌套屬性也是狀態物件。
我想影響所有擁有一個屬性、一組嵌套屬性或擁有一個具有指定值的屬性的物件。
我的想法是創建一個“控制器”,它將原始串列作為單獨的串列存盤在控制器類的物件實體中。每個原始屬性和值都將指向包含這些屬性或值的物件串列,基本設計如下:
class Controller:
def __init__(self, list_of_objects):
self.list_of_objects = list_of_objects # Our list of objects from above
self.create_hierarchy_of_objects()
def create_hierarchy_of_objects(self):
for o in self.list_of_objects:
# Does something here
該create_hierarchy_of_objects方法運行后,我將能夠執行以下操作:
Controller.country.Kenya將包含 self.country 為“肯尼亞”的所有物件的串列,即 object1、object2、object4Controller.disease將包含具有 self.disease 屬性的所有物件的串列,即 object1 和 object2Controller.risk_factor.smoking.Current將包含具有該組屬性的物件串列,即 object3
問題是如何create_hierarchy_of_objects作業?
我幾點澄清
- 嵌套是任意長的,并且值可能相同,例如
self.risk_factor.attribute1.attribute2 = "foo"self.risk_factor.attribtue3.attribute4 = "foo"也是。
- 可能有一種更簡單的方法可以做到這一點,我歡迎任何建議。
uj5u.com熱心網友回復:
如果您必須處理超過一百萬個物件,則生成額外的層次結構可能不是最佳解決方案。這將需要許多額外的物件并浪費大量時間來創建層次結構。每當發生變化時,也需要更新層次結構list_of_objects。
因此,我建議使用迭代器和類似 XPath 的原則來使用更通用和動態的方法。讓我們稱之為OPath。該類OPath是一個輕量級物件,它只是將屬性連接到一種屬性路徑。它還保留對原始條目物件串列的參考。最后,它僅基于屬性,因此適用于任何型別的物件。
實際查找發生在我們開始遍歷OPath物件時(例如,將物件放入 alist()中,使用for-loop,...)。回傳一個迭代器,它根據OPath最初提供的串列中的實際內容,根據屬性路徑遞回查找匹配的物件。它yield是一個接一個的匹配物件,以避免使用完全填充的匹配物件創建不必要的串列。
class OPath:
def __init__(self, objects, path = []):
self.__objects = objects
self.__path = path
def __getattr__(self, __name):
return OPath(self.__objects, self.__path [__name])
def __iter__(self):
yield from (__object for __object in self.__objects if self.__matches(__object, self.__path))
@staticmethod
def __matches(__object, path):
if path:
if hasattr(__object, path[0]):
return OPath.__matches(getattr(__object, path[0]), path[1:])
if __object == path[0] and len(path) <= 1:
return True
return False
return True
if __name__ == '__main__':
class State:
def __init__(self, state_dictionary):
self._state_dictionary = state_dictionary
for key, value in self._state_dictionary.items():
if isinstance(value, dict):
value = State(value)
setattr(self, key, value)
o1 = State({ "country":"Kenya", "disease": "breast cancer" })
o2 = State({ "country":"Kenya", "disease": "diabetes" })
o3 = State({ "country":"Ireland", "risk_factor": { "smoking":"Current" } })
o4 = State({ "country":"Kenya", "risk_factor": { "smoking":"Previous" } })
# test cases with absolute paths
print("Select absolute")
path = OPath([o1, o2, o3, o4])
print(list(path) == [o1, o2, o3, o4])
print(list(path.country) == [o1, o2, o3, o4])
print(list(path.country.Kenya) == [o1, o2, o4])
print(list(path.disease) == [o1, o2])
print(list(path.disease.diabetes) == [o2])
print(list(path.risk_factor.smoking) == [o3, o4])
print(list(path.risk_factor.smoking.Current) == [o3])
print(list(path.doesnotexist.smoking.Current) == [])
print(list(path.risk_factor.doesnotexist.Current) == [])
print(list(path.risk_factor.smoking.invalidvalue) == [])
print(list(path.risk_factor.doesnotexist.Current.invalidpath) == [])
# test cases with relative paths
country = OPath([o1, o2, o3, o4], ["country"])
print("Select relative from country:")
print(list(country) == [o1, o2, o3, o4])
print(list(country.Kenya) == [o1, o2, o4])
print("Select all with country=Kenya")
kenya = OPath([o1, o2, o3, o4], ['country', 'Kenya'])
print(list(kenya) == [o1, o2, o4])
預計輸出將True適用于所有測驗用例。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/411919.html
標籤:
上一篇:從物件陣列中洗掉重復項并更新鍵
