简体   繁体   中英

Javascript compare results in a single object array and append if a value matches within the same object array

I'm looking to try and concatenate the array down to the base folder hierarchy.

In my example below "Level 1" is the lowest level there are no children folders to this level. The "other level" will have a multitude of different folders all under the "Top Level"

The array I have the data is as follows:

[{ id: "Top Level", outerpath: "test plan", innerpath: "Regression" },
 { id: "other level", outerpath: "Regression", innerpath: "area 1" },
 { id: "Level 1", outerpath: "area 1", innerpath: "Subarea 1" },
 { id: "Level 1", outerpath: "area 1", innerpath: "Subarea 2" },
 { id: "Level 1", outerpath: "Regression", innerpath: "area 2" }]

Now I needing the results of the concaternation of the data within the object array to look like this:

test plan/Regression/area 1/Subarea 1
test plan/Regression/area 1/Subarea 2
test plan/Regression/area 2

However I have no clue how to start this. Perhaps its along the lines of a loop through the array matching "innerpath" and "outpath" values then pushing the completed data to another array?

Any ideas would be really useful.

UPDATE:

To expand on my question the array is dynamic and depending of the results of the API it might be like this array

[{ id: "Top Level", outerpath: "test plan", innerpath: "Regression" }
{ id: "other level", outerpath: "Regression", innerpath: "area 1" }
{ id: "Level 1", outerpath: "area 1", innerpath: "Subarea 1" }
{ id: "other level", outerpath: "area 1", innerpath: "Subarea 2" }
{ id: "Level 1", outerpath: "Regression", innerpath: "area 2" }
{ id: "Top Level", outerpath: "test plan", innerpath: "other testing" }
{ id: "Level 1", outerpath: "other testing", innerpath: "other testing area 1" }
{ id: "other level", outerpath: "other testing", innerpath: "other testing area 2" }
{ id: "Level 1", outerpath: "other testing area 2", innerpath: "other testing subarea 1" }
{ id: "Level 1", outerpath: "Subarea 2", innerpath: "SubSubArea 1" }]

So there isn't going to be just one top level it could be multiple top levels as the folder "test plan" will have multiple folders with some of them with subfolders of their own.

在此处输入图片说明

My code that collated the data from the callback from the API call is here:

let testSuiteData = res;
           testSuiteData.value.forEach(async testSuiteItem => {
                  console.log(testSuiteItem);
    
                  if(!testSuiteItem.hasChildren === true) // Level 1
                  {
                      console.log(testSuiteItem.parentSuite.name + '/' + testSuiteItem.name)
                      folderHierarchy.path.push({
                          id: 'Level 1',
                          outerpath: testSuiteItem.parentSuite.name,
                          innerpath: testSuiteItem.name
                      })
                            
                  }
                  else if(testSuiteItem.hasChildren === true ) // other levels
                  {
                      if(testSuiteItem.parentSuite.name === testSuiteItem.plan.name) // Top Level
                      {
                          console.log(testSuiteItem.parentSuite.name + '/' + testSuiteItem.name)
                          folderHierarchy.path.push({
                              id: 'Top Level',
                              outerpath: testSuiteItem.parentSuite.name,
                              innerpath: testSuiteItem.name
                          })
                      }
                      else{ // Other Levels
                          console.log(testSuiteItem.parentSuite.name + '/' + testSuiteItem.name)
                          folderHierarchy.path.push({
                              id: 'other level',
                              outerpath: testSuiteItem.parentSuite.name,
                              innerpath: testSuiteItem.name
                          })
                      }
                  }
    
                        
                  console.log(folderHierarchy.path);

You could do something like this

 const array = [{ id: "Top Level", outerpath: "test plan", innerpath: "Regression" }, { id: "other level", outerpath: "Regression", innerpath: "area 1" }, { id: "Level 1", outerpath: "area 1", innerpath: "Subarea 1" }, { id: "Level 1", outerpath: "area 1", innerpath: "Subarea 2" }, { id: "Level 1", outerpath: "Regression", innerpath: "area 2" }] const obj = {}; // a map of all our paths const topLevel = array.splice(0, 1)[0]; // removing the top level from array as it is not needed, and for further reference const base = `${topLevel.outerpath}/${topLevel.innerpath}`; // creating our default path, which we will use as a reference later for (let i = 0; i < array.length; i++) { const path = array[i].outerpath.split(' '); // creating a unique key for our map const key = path[1] ? path[1] : path[0]; if (!obj[key]) obj[key] = []; if (path[0] == 'area') obj[key].push(`${base}/${array[i].outerpath}/${array[i].innerpath}`); else if (path[0] == 'Regression') obj[key].push(`${base}/${array[i].innerpath}`) } console.log(obj);

My approach in steps:

  1. find first element
  2. find childs of this element
  3. check childs of child elements
  4. repeat step 3 until you have whole tree
  5. flatten your tree

Try to do it yourself and only then check this example on how it can be achieved.

 class TreeList { tree = null; isTopLevel = (level) => { let topLevel = true; this.data.map(lv => { if (lv.innerPath === level.outerPath) { topLevel = false; } }); return topLevel; } createTree = (data) => { this.data = data; data.map(level => { if (this.isTopLevel(level)) { this.tree = level; } }); if (this.tree === null) { console.error('Couldn\\'t find top level.'); return; } this.tree = this.findChildLevels(this.tree); return this.flattenObject(this.tree); } findChildLevels = (level) => { this.data.map(lv => { if (lv.outerPath === level.innerPath) { if (level?.children === null || level?.children === undefined) { level.children = []; } level.children.push(this.findChildLevels(lv)); } }); return level; } flattenObject = (level) => { let currentPath = level.outerPath; let list = []; if (level?.children !== undefined && level?.children !== null) { level.children.map(child => { this.flattenChildren(list, currentPath, child); }); } else { list = [currentPath]; } return list } flattenChildren = (list, currentPath, level) => { if (level?.children !== undefined && level?.children !== null) { // currentPath += `/${level.outerPath}`; currentPath += '/' + level.outerPath; level.children.map(child => { this.flattenChildren(list, currentPath, child) }); } else { // list.push(`${currentPath}/${level.outerPath}/${level.innerPath}`); list.push(currentPath + '/' + level.outerPath + '/' + level.innerPath); } return list; } } const tl = new TreeList() const list = tl.createTree([ {id: "Top Level", outerPath: "test plan", innerPath: "Regression"}, {id: "other level", outerPath: "Regression", innerPath: "area 1"}, {id: "Level 1", outerPath: "area 1", innerPath: "Subarea 1"}, {id: "Level 1", outerPath: "area 1", innerPath: "Subarea 2"}, {id: "Level 1", outerPath: "Regression", innerPath: "area 2"} ]); list.map(item => { console.log(item); });

I think we can simplify this a bit more by first creating a list of all unique innerpath values which do not also appear as outerpath values and then traversing backwards from each.

Here's how that would look, using your latest dynamic array of objects:

I excluded the id property values from your original data, as it did not appear to be getting used anywhere, just for the sake of keeping this example concise, but you can certainly add that back in your final version.

 const data = [ { outerpath: "test plan", innerpath: "Regression" }, { outerpath: "Regression", innerpath: "area 1" }, { outerpath: "area 1", innerpath: "Subarea 1" }, { outerpath: "area 1", innerpath: "Subarea 2" }, { outerpath: "Regression", innerpath: "area 2" }, { outerpath: "test plan", innerpath: "other testing" }, { outerpath: "other testing", innerpath: "other testing area 1" }, { outerpath: "other testing", innerpath: "other testing area 2" }, { outerpath: "other testing area 2", innerpath: "other testing subarea 1" }, { outerpath: "Subarea 2", innerpath: "SubSubArea 1" } ]; const outerpaths = data.map(({ outerpath }) => outerpath), innerpaths = data.map(({ innerpath }) => innerpath).filter(innerpath => !outerpaths.includes(innerpath)); const concatenated = innerpaths.map(innerpath => { let obj = data.find(obj => obj.innerpath === innerpath), str = obj.outerpath + '/' + innerpath, i = 0; do { obj = data.find(({ innerpath }) => obj.outerpath === innerpath); if (obj) str = obj.outerpath + '/' + str; i++; } while (i < 20 && obj) return str; }); console.log(concatenated.join('\\n'));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM