【问题标题】:Javascript compare results in a single object array and append if a value matches within the same object arrayJavascript 比较结果为单个对象数组,如果值在同一对象数组中匹配,则追加
【发布时间】:2021-11-03 13:45:45
【问题描述】:

我正在尝试将数组连接到基本文件夹层次结构。

在下面的示例中,“级别 1”是最低级别,该级别没有子文件夹。 “其他级别”将在“顶级”下有许多不同的文件夹

我有数据的数组如下:

[{ 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" }]

现在我需要对象数组中数据的串联结果如下所示:

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

但是我不知道如何开始。也许它通过匹配“innerpath”和“outpath”值的数组循环,然后将完成的数据推送到另一个数组?

任何想法都会非常有用。

更新:

为了扩展我的问题,数组是动态的,根据 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" }]

因此不会只有一个顶层,它可能是多个顶层,因为文件夹“测试计划”将有多个文件夹,其中一些文件夹有自己的子文件夹。

我从 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);

【问题讨论】:

  • 最后一个条目(带有area 2)不应该在other level上吗?我会尝试从输入数组创建一个树结构,然后遍历它以输出路径
  • 不,因为它下面没有任何子文件夹,所以它是最低的。例如没有测试计划/Regression/area 2/"subfodlers"
  • 嗨@Daniel,有机会请看看我的解决方案。它使用do..while 循环动态工作,从每个最深的innerpath 值遍历到最高的ancestor。我认为首先获得最深的innerpath 值列表然后从那里向后工作是明智的。如果您有任何问题,请告诉我!
  • @Daniel **还值得注意的是,虽然我选择了 do..while 循环,但您也可以在这里使用递归,尽管在我看来 do..while 循环更干净,因为它没有创建额外的不必要的函数声明。

标签: javascript arrays object


【解决方案1】:

我认为我们可以更简化这一点,首先创建一个列表,其中包含所有唯一的 innerpath 值,这些值不会也显示为 outerpath 值,然后从每个值向后遍历。

使用最新的动态对象数组如下所示:

我从您的原始数据中排除了 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;
  if (obj) do {
    obj = data.find(({ innerpath }) => obj.outerpath === innerpath);
    if (obj) str = obj.outerpath + '/' + str;
  } while (obj)
  return str;
});

console.log(concatenated.join('\n'));

这段代码的输出是:

test plan/Regression/area 1/Subarea 1
test plan/Regression/area 2
test plan/other testing/other testing area 1
test plan/other testing/other testing area 2/other testing subarea 1
test plan/Regression/area 1/Subarea 2/SubSubArea 1

【讨论】:

  • 嗨 Brandon McConnell - 谢谢你,它就像一个魅力:)
  • @Daniel 很高兴听到它! Lmk 如果您遇到任何问题??
  • 有没有机会扩展这个答案。一旦连接数组完成,然后将其与另一个数组匹配,然后使用新数组中连接数组中的该行。例如:Concat Array = test plan/Regression/area 2 test plan/other testing/other testing area 1 test plan/other testing/other testing area 2/other testing subarea 1 test plan/Regression/area 1/Subarea 2/SubSubArea 1 然后第二个数组有一个值 testSuiteName: "other testing subarea 1",,我们需要将它匹配到 concat 数组,然后设置一个值为数组 2 的正确信息。
  • 例如,如果连接匹配testSuiteName 然后做一些事情..... 可能是这样的:if(concatenation.map() ***Something***) { parentpath = concatenation.values(); Array2.Push({ parentSuiteName:parentpath.toString(),}) } 类似这样的事情。然而,这可能是完全错误的,所以一些建议会非常有用。 @布兰登
【解决方案2】:

你可以这样做

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

【讨论】:

  • AnanthDev - 虽然这适用于静态数组,但我的数组是动态的,或者我在后台返回 API 请求的结果,因此无法使用静态引用对 if 语句进行硬编码。它也需要动态。如果 innerpath = outerpath 之类的。
猜你喜欢
  • 2023-02-03
  • 2020-08-06
  • 1970-01-01
  • 1970-01-01
  • 2019-01-04
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
  • 2016-10-24
相关资源
最近更新 更多