簡體   English   中英

將最大值傳播到嵌套樹javascript中的父節點

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM