简体   繁体   English

Javascript比较单个对象数组中的结果,如果值在同一对象数组中匹配,则追加

[英]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.在我下面的示例中,“级别 1”是最低级别,此级别没有子文件夹。 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?也许它沿着通过匹配“innerpath”和“outpath”值的数组的循环线,然后将完成的数据推送到另一个数组?

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为了扩展我的问题,数组是动态的,根据 API 的结果,它可能像这个数组

[{ 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:我从 API 调用的回调中整理数据的代码在这里:

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重复步骤 3 直到你有整棵树
  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.我认为我们可以通过首先创建一个所有唯一的innerpath值的列表来进一步简化它,这些值也不会显示为outerpath值,然后从每个值向后遍历。

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.我从你的原始数据中排除了id属性值,因为它似乎没有在任何地方使用,只是为了保持这个例子简洁,但你当然可以在你的最终版本中添加它。

 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'));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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