有些場景使用多維哈希來存儲數據,時間復雜度恆定,簡單粗暴好用。這里記錄一下。
如下是三維哈希的簡單示意圖,建議層數不要太多,否則時間久了,自己寫的代碼都不認識。
下圖是三維哈希在內存的存儲形式,hashmap嵌套了3層。圖里一層數組存放entry和鏈表next指針,每個節點里面都存放一個數組,數組存放下一層hashcode和下一層鏈表指針。(沒有將哈希分桶鏈表完整畫出來,本圖重點是哈希嵌套)
這個數據結構我是用來解析保存不同設備的配置,每個設備有兩個配置文件。當新來一個該設備的數據(base64加密后的json序列化字符串),通過這個三維哈希層層解析,返回給用戶直觀的表象。這里不談業務,只談如何暴力存,暴力解。
/***************************************************************************** 結 構 名 : StringStu 功能描述 : 設備string文件數據結構 *****************************************************************************/ type StringStu struct { Cat_name string `json:"cat_name,omitempty"` Dev_name string `json:"dev_name,omitempty"` Pid string `json:"pid,omitempty"` Error interface{} `json:"error,omitempty"` Intfs interface{} `json:"intfs,omitempty"` Vendor_name string `json:"vendor_name,omitempty"` } /***************************************************************************** 結 構 名 : 產品string文件相關處理 功能描述 : *****************************************************************************/ func GetAllProductString() (Slice []ProfileSuidsStu) { StringStu := ReadStringFile() for _, StringOne := range StringStu { LoadDevStrings2Cache(StringOne.Pid, libf.StructToJsonStringOne(StringOne.Intfs)) } return } func ReadStringFile() []StringStu { var file string = "" var StringSlice = make([]StringStu, 0) file = libf.KeyfileT(file).GetFileName("strings.json") Byte, Error := ioutil.ReadFile(file) if Error != nil { prnLog.LogPrint(libf.LOG_ERROR, 0, false, false, "", "ReadFile error", Error) return nil } msg, ret := libf.ParseJsonByStructMsg(Byte, &StringSlice) return StringSlice } /***************************************************************************** 結 構 名 : StringIntfsStu 功能描述 : 設備string文件,設備Intfs屬性 *****************************************************************************/ type StringsIntfsStu struct { Name string `json:"name,omitempty"` //字段的中文名稱,例如:電量,背景燈光 Unit string `json:"unit,omitempty"` //單元,例如溫度°C Values map[string]string `json:"values,omitempty"` //字段值對應的中文枚舉,例如:0是關,1是開 } type ParamAttr = map[string]StringsIntfsStu var ProductStrings = make(map[string](ParamAttr), 0) /***************************************************************************** * \author pxx * \date 2018/08/25 * \brief 將所有設備的strings配置,載入一個三維哈希中。 一維哈希是ProductStrings,key為pid, 二維哈希是ParamAttr,key為字段英文名稱, 三維哈希是StringIntfsStu結構體內的Values,key為字段的值 * \param[in] * \param[out] * \return * \ingroup * \remarks ******************************************************************************/ func LoadDevStrings2Cache(pid, String string) { var ( keyListString map[string]interface{} = make(map[string]interface{}, 0) _param_attr = make(ParamAttr, 0) ) ProductStrings[pid] = _param_attr msg, ret := libf.ParseJsonByStructMsg([]byte(String), &keyListString) for key, value := range keyListString { var string1 StringsIntfsStu //注意作用域 msg, ret = libf.ParseJsonByStructMsg([]byte(libf.StructToJsonStringOne(value)), &string1) if ret != libf.Success { prnLog.LogPrint(libf.LOG_DEBUG, 0, false, false, "msg=%v,ret=%v", msg, ret) continue } _param_attr[key] = string1 } }
上面的代碼是粗暴的將所有設備的配置文件存入內存,下面則是根據這個三維哈希去解析數據。
/***************************************************************************** * \author pxx * \date 2018/08/27 * \brief 將json序列化的無結構數據,映射為結構化數據 * \param[in] * \param[out] * \return * \ingroup * \remarks 開源代碼說明:https://www.jb51.net/article/73996.htm ******************************************************************************/ func FormatUploadData(StringData string) (StructData StructUploadDataStu) { StructData.Did = gojson.Json(StringData).Get("did").Tostring() StructData.Pid = gojson.Json(StringData).Get("pid").Tostring() for k, v := range ProductProfile[StructData.Pid] { //k是字段名稱,v是這個字段的子屬性 value := gojson.Json(StringData).Get(k).Tostring() //根據設備每個字段的不同屬性,來映射對應的中文名稱,枚舉值,字符串值還有整數值 switch v.In[0] { case 1, 3: //1表示枚舉,2表示是連續型的參數,3 string StructData.Data += ProductStrings[StructData.Pid][k].Name + ":" + ProductStrings[StructData.Pid][k].Values[value] + ", " case 2: StructData.Data += ProductStrings[StructData.Pid][k].Name + ":" + value + ", " default: } } return }