在JavaScript中查找特定对象数组项的所有关联项

3

我有一个对象数组。你可以在JSONBlob.com这里找到完整数据的样例。

这是一个简化的预览:

[
  {
    "name": "Unbetitelt",
    "organizationMap": "60a55ed4e3a8973a02f910f1",
    "childrenLayout": [{
      "i": "60a64930cf1db1710b97bf7a",
    }],
    "id": "60a6472ecf1db1710b97bf4c"
  },
  {
    "name": "middleparent",
    "parentCubo": "60a6472ecf1db1710b97bf4c",
    "organizationMap": "60a55ed4e3a8973a02f910f1",
    "childrenLayout": [{
        "i": "60a64936cf1db1710b97bf7d",
      },
      {
        "i": "60a649afcf1db1710b97bfa6",
      }
    ],
    "id": "60a64930cf1db1710b97bf7a"
  },
  {
    "name": "Unbetitelt",
    "parentCubo": "60a64930cf1db1710b97bf7a",
    "organizationMap": "60a55ed4e3a8973a02f910f1",
    "childrenLayout": [
      {
        "i": "60a6494acf1db1710b97bf8f",
      },
      {
        "i": "60a64976cf1db1710b97bf9a",
      }
    ],
    "id": "60a64936cf1db1710b97bf7d"
  },
  {
    "name": "Unbetitelt",
    "parentCubo": "60a64930cf1db1710b97bf7a",
    "organizationMap": "60a55ed4e3a8973a02f910f1",
    "childrenLayout": [],
    "id": "60a649afcf1db1710b97bfa6"
  },
  {
    "name": "Unbetitelt",
    "parentCubo": "60a649c5cf1db1710b97bfb1",
    "organizationMap": "60a55ed4e3a8973a02f910f1",
    "childrenLayout": [],
    "id": "60a649efcf1db1710b97bfc4"
  }
]

这个数组中的每个对象(根数组)都有一个id和childrenLayout属性。
childrenLayout属性是一个对象数组(子数组),其中包含一个i属性,但不包含另一个childrenLayout。因此,为了找到childrenLayout数组中每个项目的子项,我们将使用这个i字段,并在根数组中查找对象。
一旦我们在根数组中找到这些对象,如果这些对象上的childrenLayout属性不是一个空数组,那么我们就必须重复相同的过程,并在该对象的childrenLayout中查找对象,从而创建与具有id x的特定对象链接的所有id列表。
因此,例如,如果我们尝试查找与id 60a6472ecf1db1710b97bf4c关联的所有项目,我们将获得以下结果:
60a64930cf1db1710b97bf7a 60a64936cf1db1710b97bf7d 60a649afcf1db1710b97bfa6 60a6494acf1db1710b97bf8f 60a64976cf1db1710b97bf9a
这是我目前的代码,显然不能按预期工作,并且仅返回上述预期项目列表中的最后三个项目:
const findChildFor = item => {
  if (item.childrenLayout.length > 0) {
    const detailsOfItems = item.childrenLayout.map(({ i }) =>
      data.find(datum => datum.id === i)
    );
    return detailsOfItems.map(itemDetails => findChildFor(itemDetails));
  } else {
    return item.id;
  }
};
const [firstItem] = data;
// TODO: Work on a way to make it return children without having to flatten it.
const childrenRelatedToFirstItem = findChildFor(firstItem);
console.log(
  'childrenRelatedToFirstItem: ',
  childrenRelatedToFirstItem.flat(10)
);

为了加速解决方案,这是一个带有目前代码的 Stackblitz 示例
非常感谢任何帮助。

1
抱歉,我不太明白你想要实现什么?你是想在数组中找到所有具有特定childrenLayout i的对象吗?如果它起作用了,你能否举个例子说明返回的对象应该是什么样子的? - Breezer
总的来说,这有点棘手。所以考虑到有一个数组,我想找到与该数组中特定对象相关联的所有对象。如果可以的话,我已经在上面给出了一个示例。不幸的是,我的逻辑似乎没有按预期工作。您能否请检查我在问题末尾链接的示例stackblitz?那里有我目前编写的代码。 - SiddAjmera
你想要每个childLayout的第一个数组吗? - Breezer
1
啊,我现在明白了。 - Breezer
我相信我已经解决了它。我没有真正注意到我正在获取重复的值。但是我认为现在用 [...new Set(linkedChildren)] 修复了。我将使用解决方案更新此线程。 - SiddAjmera
显示剩余2条评论
3个回答

1
我找到了一个解决方案。代码并不是很复杂。希望这对你有所帮助。
const findChildFor = (arr, id, output) => {
    const item = arr.find(obj => obj.id === id);
    if (item) {
        const childs = item.childrenLayout;
        for (let child of childs) {
            output.push(child.i);
            findChildFor(arr, child.i, output);
        }
    }
}

output = [];
findChildFor(data, '60a6472ecf1db1710b97bf4c', output);
console.log(output);

1
这段数据看起来像是一个图形描述。以下是我对该问题的解决方案,具有优化的时间复杂度并处理循环连接。
const findAllChildren = (arr, id) => {
  // to find each child with O(1) access time
  const familyMap = new Map(arr.map(it => [it.id, it.childrenLayout]));
  // to check if a child has been collected with O(1) access time   
  const resultSet = new Set();
  const findChildrenFor = (parentId) => {
    familyMap.get(parentId).forEach(({i}) => {
      // in a case of a cyclic graph
      if (!resultSet.has(i)) {
        resultSet.add(i);
        findChildrenFor(i);
      }
    });
  };
  return Array.from(findChildrenFor(id));
};

1
我以一种不同的方式提出了一个解决方案,但达到了你想要的结果。
dataArray.reduce((acc,cur)=>{
    acc[cur.id] = [];
    cur.childrenLayout.map(child=>acc[cur.id].push(child.i))
    Object.entries(acc).map(obj=>{
       if(obj[1].includes(cur.id)){
          cur.childrenLayout.map(child=>acc[obj[0]].push(child.i))
       }
    })
   return acc;
},{})

任何问题请在评论区留言。

const dataArray = [
  {
    "name": "Unbetitelt",
    "organizationMap": "60a55ed4e3a8973a02f910f1",
    "childrenLayout": [{
      "i": "60a64930cf1db1710b97bf7a",
    }],
    "id": "60a6472ecf1db1710b97bf4c"
  },
  {
    "name": "middleparent",
    "parentCubo": "60a6472ecf1db1710b97bf4c",
    "organizationMap": "60a55ed4e3a8973a02f910f1",
    "childrenLayout": [{
        "i": "60a64936cf1db1710b97bf7d",
      },
      {
        "i": "60a649afcf1db1710b97bfa6",
      }
    ],
    "id": "60a64930cf1db1710b97bf7a"
  },
  {
    "name": "Unbetitelt",
    "parentCubo": "60a64930cf1db1710b97bf7a",
    "organizationMap": "60a55ed4e3a8973a02f910f1",
    "childrenLayout": [
      {
        "i": "60a6494acf1db1710b97bf8f",
      },
      {
        "i": "60a64976cf1db1710b97bf9a",
      }
    ],
    "id": "60a64936cf1db1710b97bf7d"
  },
  {
    "name": "Unbetitelt",
    "parentCubo": "60a64930cf1db1710b97bf7a",
    "organizationMap": "60a55ed4e3a8973a02f910f1",
    "childrenLayout": [],
    "id": "60a649afcf1db1710b97bfa6"
  },
  {
    "name": "Unbetitelt",
    "parentCubo": "60a649c5cf1db1710b97bfb1",
    "organizationMap": "60a55ed4e3a8973a02f910f1",
    "childrenLayout": [],
    "id": "60a649efcf1db1710b97bfc4"
  }
]

const childFinder = arr => {
  return arr.reduce((acc,cur)=>{
    acc[cur.id] = [];
cur.childrenLayout.map(child=>acc[cur.id].push(child.i))
Object.entries(acc).map(obj=>{
    if(obj[1].includes(cur.id)){
cur.childrenLayout.map(child=>acc[obj[0]].push(child.i))
    }
})
return acc;
},{})
}

console.log(childFinder(dataArray))


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接