[英]Propagate max value to parent nodes in nested tree javascript
有一個像下面這樣的嵌套數組:
[
{
"id": 100,
"idParent": null,
"anidatedView": null,
"state": null,
"warningHighThreshold": null,
"dangerHighThreshold": null,
"lvl": 1,
"children": [
{
"id": 139,
"idParent": 100,
"anidatedView": null,
"state": null,
"warningHighThreshold": null,
"dangerHighThreshold": null,
"lvl": 2,
"children": [
{
"id": 186,
"idParent": 139,
"anidatedView": 279,
"state": 15.58,
"warningHighThreshold": 80,
"dangerHighThreshold": 100,
"lvl": 3,
"children": []
},
{
"id": 189,
"idParent": 139,
"anidatedView": 193,
"state": 40.65,
"warningHighThreshold": 80,
"dangerHighThreshold": 100,
"lvl": 3,
"children": []
}
]
},
{
"id": 140,
"idParent": 100,
"anidatedView": null,
"state": null,
"warningHighThreshold": null,
"dangerHighThreshold": null,
"lvl": 2,
"children": [
{
"id": 193,
"idParent": 140,
"anidatedView": 183,
"state": 65.41,
"warningHighThreshold": 92,
"dangerHighThreshold": 100,
"lvl": 3,
"children": []
}
]
},
{
"id": 141,
"idParent": 100,
"anidatedView": null,
"state": null,
"warningHighThreshold": null,
"dangerHighThreshold": null,
"lvl": 2,
"children": [
{
"id": 194,
"idParent": 141,
"anidatedView": 143,
"state": 60.77,
"warningHighThreshold": 90,
"dangerHighThreshold": 100,
"lvl": 3,
"children": []
},
{
"id": 195,
"idParent": 141,
"anidatedView": 436,
"state": 59.13,
"warningHighThreshold": 90,
"dangerHighThreshold": 100,
"lvl": 3,
"children": []
}
]
}
]
}
]
我正在嘗試將狀態的最大值(還有該最大節點的 warningHighThreshold 和 riskHighThreshold)傳播到所有父節點。
狀態和閾值將始終在樹的最后一層可用。
知道如何用遞歸來做到這一點嗎?
提前致謝!
我終於設法解決了這個問題。 我把我的解決方案留給那些可能有同樣問題的人。
const populateState = item => {
if (item.children.length) {
const maxValue = item.children
.map(child => populateState(child))
.filter(({ state }) => state != null)
.reduce((maxValue, value) => (value.state > maxValue.state ? value : maxValue), { state: -1 })
item.state = maxValue.state
item.warningHighThreshold = maxValue.warningHighThreshold
item.dangerHighThreshold = maxValue.dangerHighThreshold
return maxValue
} else {
const { state, warningHighThreshold, dangerHighThreshold } = item
return { state, warningHighThreshold, dangerHighThreshold }
}
}
用法:
(數組變量是我在問題中定義的列表)
populateState({ children: array})
歡迎任何代碼增強。
試試這個:
const list = JSON.parse(`[ { "id": 100, "idParent": null, "anidatedView": null, "state": null, "warningHighThreshold": null, "dangerHighThreshold": null, "lvl": 1, "children": [ { "id": 139, "idParent": 100, "anidatedView": null, "state": null, "warningHighThreshold": null, "dangerHighThreshold": null, "lvl": 2, "children": [ { "id": 186, "idParent": 139, "anidatedView": 279, "state": 15.58, "warningHighThreshold": 80, "dangerHighThreshold": 100, "lvl": 3, "children": [] }, { "id": 189, "idParent": 139, "anidatedView": 193, "state": 40.65, "warningHighThreshold": 80, "dangerHighThreshold": 100, "lvl": 3, "children": [] } ] }, { "id": 140, "idParent": 100, "anidatedView": null, "state": null, "warningHighThreshold": null, "dangerHighThreshold": null, "lvl": 2, "children": [ { "id": 193, "idParent": 140, "anidatedView": 183, "state": 65.41, "warningHighThreshold": 92, "dangerHighThreshold": 100, "lvl": 3, "children": [] } ] }, { "id": 141, "idParent": 100, "anidatedView": null, "state": null, "warningHighThreshold": null, "dangerHighThreshold": null, "lvl": 2, "children": [ { "id": 194, "idParent": 141, "anidatedView": 143, "state": 60.77, "warningHighThreshold": 90, "dangerHighThreshold": 101, "lvl": 3, "children": [] }, { "id": 195, "idParent": 141, "anidatedView": 436, "state": 59.13, "warningHighThreshold": 90, "dangerHighThreshold": 100, "lvl": 3, "children": [] } ] } ] } ]`); function getHigh(obj, prop) { let ret = null; for(let n = 0; n < 2; n++) { for(let i = 0; i < obj.length; i++) { const r = getHigh(obj[i].children, prop); if (r > obj[i][prop]) { obj[i][prop] = r; ret = r; } if (obj[i][prop] > ret) ret = obj[i][prop]; } } return ret; } console.log("warningHighThreshold", getHigh(list, "warningHighThreshold")); console.log(JSON.stringify(list, null, 2)); console.log("dangerHighThreshold", getHigh(list, "dangerHighThreshold")); console.log(JSON.stringify(list, null, 2));
這種問題可以用深度優先搜索來解決......
let input = [{ "id": 100, "idParent": null, "anidatedView": null, "state": null, "warningHighThreshold": null, "dangerHighThreshold": null, "lvl": 1, "children": [{ "id": 139, "idParent": 100, "anidatedView": null, "state": null, "warningHighThreshold": null, "dangerHighThreshold": null, "lvl": 2, "children": [{ "id": 186, "idParent": 139, "anidatedView": 279, "state": 15.58, "warningHighThreshold": 80, "dangerHighThreshold": 100, "lvl": 3, "children": [] }, { "id": 189, "idParent": 139, "anidatedView": 193, "state": 40.65, "warningHighThreshold": 80, "dangerHighThreshold": 100, "lvl": 3, "children": [] }] }, { "id": 140, "idParent": 100, "anidatedView": null, "state": null, "warningHighThreshold": null, "dangerHighThreshold": null, "lvl": 2, "children": [{ "id": 193, "idParent": 140, "anidatedView": 183, "state": 65.41, "warningHighThreshold": 92, "dangerHighThreshold": 100, "lvl": 3, "children": [] }] }, { "id": 141, "idParent": 100, "anidatedView": null, "state": null, "warningHighThreshold": null, "dangerHighThreshold": null, "lvl": 2, "children": [{ "id": 194, "idParent": 141, "anidatedView": 143, "state": 60.77, "warningHighThreshold": 90, "dangerHighThreshold": 100, "lvl": 3, "children": [] }, { "id": 195, "idParent": 141, "anidatedView": 436, "state": 59.13, "warningHighThreshold": 90, "dangerHighThreshold": 100, "lvl": 3, "children": [] }] }] }] let keys = ["state", "warningHighThreshold", "dangerHighThreshold"]; function populateState(children) { for (let item of children) Object.assign(item, populateState(item.children)) return children.length ? Object.assign(...keys.map(k => ({ [k]: Math.max(...children.map(o => o[k])) }))) : {} } console.log("Max Threshold:", populateState(input), "\\n\\nInput:", input)
這是一個非變異版本,它似乎可以做你想做的事,返回一個最大值匯總到其祖先的新對象:
const collectMax = (xs) => xs .map (({children, kids = collectMax (children), ...rest}) => ({ ...rest, state: Math.max (rest.state, ... kids .map (k => k .state)), warningHighThreshold: Math .max (rest .warningHighThreshold, ... kids .map (k => k .warningHighThreshold)), dangerHighThreshold: Math .max (rest. dangerHighThreshold, ... kids .map (k => k .dangerHighThreshold)), children: kids })) const list = [{id: 100, idParent: null, anidatedView: null, state: null, warningHighThreshold: null, dangerHighThreshold: null, lvl: 1, children: [{id: 139, idParent: 100, anidatedView: null, state: null, warningHighThreshold: null, dangerHighThreshold: null, lvl: 2, children: [{id: 186, idParent: 139, anidatedView: 279, state: 15.58, warningHighThreshold: 80, dangerHighThreshold: 100, lvl: 3, children: []}, {id: 189, idParent: 139, anidatedView: 193, state: 40.65, warningHighThreshold: 80, dangerHighThreshold: 100, lvl: 3, children: []}]}, {id: 140, idParent: 100, anidatedView: null, state: null, warningHighThreshold: null, dangerHighThreshold: null, lvl: 2, children: [{id: 193, idParent: 140, anidatedView: 183, state: 65.41, warningHighThreshold: 92, dangerHighThreshold: 100, lvl: 3, children: []}]}, {id: 141, idParent: 100, anidatedView: null, state: null, warningHighThreshold: null, dangerHighThreshold: null, lvl: 2, children: [{id: 194, idParent: 141, anidatedView: 143, state: 60.77, warningHighThreshold: 90, dangerHighThreshold: 101, lvl: 3, children: []}, {id: 195, idParent: 141, anidatedView: 436, state: 59.13, warningHighThreshold: 90, dangerHighThreshold: 100, lvl: 3, children: []}]}]}] console .log ( collectMax (list) )
.as-console-wrapper {max-height: 100% !important; top: 0}
我們首先將函數遞歸地應用於children
節點,然后將我們的測試值與來自每個子節點的適當值組合在一起,並取最大值,將最大值分配給當前對象以用於適當的屬性。
但我認為從中提取輔助函數會更清晰:
const collect = (ps, o, k) => Object.assign (... ps .map (p => ({
[p]: Math.max (o [p], ... k .map (k => k [p]))
})))
const collectMax = (xs) => xs .map (({children, kids = collectMax (children), ...rest}) => ({
... rest,
... collect (['state', 'warningHighThreshold', 'dangerHighThreshold'], rest, kids),
children: kids
}))
這做同樣的事情,但稍微簡化了代碼,並使添加新的最大值屬性變得微不足道。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.