簡體   English   中英

從數組javascript創建嵌套對象

[英]Create nested object from array javascript

我有一個 SharePoint 列表,我通過 REST 在 javascript 中進行操作。 我需要將數組從 REST 轉換為嵌套對象。 我正在基於結構構建導航菜單。 該數組由 ID、Title、Parent 和 Level 組成。 級別是 Top、Mid 或 Bot,Parent 列出作為其父項的條目的 Title。

let orgs = [{
    id: "0",
    title: "A",
    parent: "",
    level: "Top"
  },{
    id: "1",
    title: "Org A1",
    parent: "A",
    level: "Middle"
  },
  {
    id: "2",
    title: "Org A2",
    parent: "A",
    level: "Middle"
  },
  {
    id: "3",
    title: "Org A3",
    parent: "A",
    level: "Middle"
  },
  {
    id: "5",
    title: "Org A1-A",
    parent: "Org A1",
    level: "Bottom"
  },
  {
    id: "6",
    title: "Org A1-B",
    parent: "Org A1",
    level: "Bottom"
  },
  {
    id: "7",
    title: "Org A2-A",
    parent: "Org A2",
    level: "Bottom"
  },
  {
    id: "8",
    title: "Org A2-B",
    parent: "Org A2",
    level: "Bottom"
  },  
  {
    id: "9",
    title: "Org A3-A",
    parent: "Org A3",
    level: "Bottom"
  },
  {
    id: "10",
    title: "Org A3-B",
    parent: "Org A3",
    level: "Bottom"
  }
];

我正在嘗試遍歷數組並將子項的標題添加到適當的父項。 對象的目標結構是:

const orgObj = {
  Title: "Org A",
  mid: [{
    Title: "Org A1",
    bot: [{
      Title: "Org A1-A"
    }, {
      Title: "Org A1-B"
    }]
  }, {
    Title: "Org A2",
    bot: [{
      Title: "Org A2-A"
    }, {
      Title: "Org A2-B"
    }]
  }, {
    Title: "Org A3",
    bot: [{
      Title: "Org A3-A"
    }, {
      Title: "Org A3-B"
    }]
  }]
};

我試圖使用地圖功能,但我無法讓結果正常工作。 我一直在這幾天斷斷續續,似乎無法讓它工作。 到目前為止,我無法訪問我在當前位置嘗試過的代碼,但我會在可以獲得它時嘗試更新。 在我看來,這不應該是復雜的。

這是一種方法...

 let orgs = [{ id: "0", title: "Org A", parent: "", level: "Top" },{ id: "1", title: "Org A1", parent: "Org A", level: "Middle" }, { id: "2", title: "Org A2", parent: "Org A", level: "Middle" }, { id: "3", title: "Org A3", parent: "Org A", level: "Middle" }, { id: "5", title: "Org A1-A", parent: "Org A1", level: "Bottom" }, { id: "6", title: "Org A1-B", parent: "Org A1", level: "Bottom" }, { id: "7", title: "Org A2-A", parent: "Org A2", level: "Bottom" }, { id: "8", title: "Org A2-B", parent: "Org A2", level: "Bottom" }, { id: "9", title: "Org A3-A", parent: "Org A3", level: "Bottom" }, { id: "10", title: "Org A3-B", parent: "Org A3", level: "Bottom" } ]; let roots = {}; orgs.forEach(org => { if (org.parent) { let parent = orgs.find(o => o.title === org.parent) if (parent.level === 'Top') { if (!parent.mid) parent.mid = []; parent.mid.push(org); } else if (parent.level === 'Middle') { if (!parent.bot) parent.bot = []; parent.bot.push(org); } } else { roots[org.title] = org; } }) console.log(JSON.stringify(Object.values(roots), null, 2));

您可以使用以下算法在線性時間O(n)為您構建樹。

我在這里大量使用Maps來保持運行時線性。

首先,我創建了一個將每個title映射到相應數據的Map 我稍后需要這個,以便我可以快速查找組織可能擁有的任何父級的數據。 結果將是這樣的:

Map(10) {
  'A' => { id: '0', title: 'A', parent: '', level: 'Top' },
  'Org A1' => { id: '1', title: 'Org A1', parent: 'A', level: 'Middle' },
  'Org A2' => { id: '2', title: 'Org A2', parent: 'A', level: 'Middle' },
  'Org A3' => { id: '3', title: 'Org A3', parent: 'A', level: 'Middle' },
  'Org A1-A' => { id: '5', title: 'Org A1-A', parent: 'Org A1', level: 'Bottom' },
  'Org A1-B' => { id: '6', title: 'Org A1-B', parent: 'Org A1', level: 'Bottom' },
  'Org A2-A' => { id: '7', title: 'Org A2-A', parent: 'Org A2', level: 'Bottom' },
  'Org A2-B' => { id: '8', title: 'Org A2-B', parent: 'Org A2', level: 'Bottom' },
  'Org A3-A' => { id: '9', title: 'Org A3-A', parent: 'Org A3', level: 'Bottom' },
  'Org A3-B' => { id: '10', title: 'Org A3-B', parent: 'Org A3', level: 'Bottom' }
}

然后我還在級別和道具名稱之間創建一個映射,以說明您沒有統一的children道具,而是midbot ,具體取決於父級。

現在開始實際的樹構建。 我再次使用reduce()遍歷所有組織,並從一個空的 JavaScript 對象開始。 對於每個項目,我創建目標對象( newObj ),它只包含Title並使用上面的Map獲取父對象。 如果沒有父元素,這是最頂層的元素。

如果它不是父對象,我可以使用我的quickRefs MaporgChart對象中查找對父對象的引用。 然后我引用了樹中的父節點。 現在我需要根據父級的級別獲取children級屬性midbot的名稱。

現在使用該屬性名稱,我可以為父節點分配這個新屬性,其值為新的子對象。 如果父對象已經有一個子對象,我可以簡單地將另一個子對象推送到該數組上,如果沒有,我需要創建一個新數組並將子對象推送到該數組上。

最后但並非最不重要的一點是,我需要將對新對象的引用插入到我的quickRefs Map中,所以如果我以后遇到一個對象是現在插入的項目的子對象,我可以如上所述直接將子對象分配給該對象。

 const input = [ { id: "0", title: "A", parent: "", level: "Top", }, { id: "1", title: "Org A1", parent: "A", level: "Middle", }, { id: "2", title: "Org A2", parent: "A", level: "Middle", }, { id: "3", title: "Org A3", parent: "A", level: "Middle", }, { id: "5", title: "Org A1-A", parent: "Org A1", level: "Bottom", }, { id: "6", title: "Org A1-B", parent: "Org A1", level: "Bottom", }, { id: "7", title: "Org A2-A", parent: "Org A2", level: "Bottom", }, { id: "8", title: "Org A2-B", parent: "Org A2", level: "Bottom", }, { id: "9", title: "Org A3-A", parent: "Org A3", level: "Bottom", }, { id: "10", title: "Org A3-B", parent: "Org A3", level: "Bottom", }, ]; // store titles to their data so we can find a parent object in constant time const map = input.reduce((all, cur) => (all.set(cur.title, cur), all), new Map()); // mapping for the property names // if the parent is level "Top", we need to use "mid" // if the parent is level "Middle", we need to use "bot" const mapLevelToPropName = { Top: "mid", Middle: "bot", } // stores references to objects within the object, so they can be accessed in constant time const quickRefs = new Map(); const output = input.reduce((orgChart, org) => { const parent = map.get(org.parent); const newObj = { Title: org.title } if(parent === undefined) { // top most org orgChart = newObj } else { // some org in the middle which has a parent // get the reference to the parent within the JS object using the quickRefs map const refToParentObj = quickRefs.get(org.parent) // determine the name of the "children" property based on the level of the parent const propName = mapLevelToPropName[parent.level]; // check if there already are childrens (mid, bot) // if yes: append another one to array if(refToParentObj[propName]) refToParentObj[propName].push(newObj); // if no: add new object within an array else refToParentObj[propName] = [newObj]; } // add a reference to the new object into the quickRefs map so // when we find a child we can just grab that reference and add the child quickRefs.set(org.title, newObj); return orgChart; }, {}) console.log(JSON.stringify(output, null, 2));
 .as-console-wrapper { max-height: 100% !important; top: 0; }

此實現假定子組織僅出現在輸入數組中的父組織之后,但適用於深度嵌套的結構(盡管“mid”、“bot”功能可能不適合此)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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