如何使用迭代的结果重新迭代?

问题描述

我需要根据条件从另一个数组创建一个新数组: 例如来自一个数组

mainArr: [
        {
            "id":1,"name":"root"
        },{
            "id":2,"parentId":1,"name":"2"
        },{
            "id":148,"parentId":2,"name":"3"
        },{
            "id":151,"parentId":148,"name":"4"
        },{
            "id":152,"parentId":151,"name":"5"
        }
    ]

我需要创建一个数组 ['1','2','148','151'],这意味着从“parentId”到“id”的路径:152 - (此函数的参数)。

我认为主要逻辑可以是这样的:

const parentsArr = [];
mainArr.forEach((item) => {
    if (item.id === id) {
        parentsArr.unshift(`${item.parentId}`);
    }

并且结果 {item.parentId} 应该用于再次迭代。但我不明白该怎么做...

解决方法

您可以为此使用递归函数。首先,您可以将数组转换为 Map,其中每个对象的每个 id 都指向其对象。这样做可以让您有效地 .get() 具有给定 id 的对象。对于每个对象,您都可以获得 parentId,如果已定义,则再次运行您的 traverse() 对象以搜索父 id。当你再也找不到 parentid 时,你就在 root 处,这意味着你可以返回一个空数组来表示不存在 parentid 对象:

const arr = [{"id":1,"name":"root"},{"id":2,"parentId":1,"name":"2"},{"id":148,"parentId":2,"name":"3"},{"id":151,"parentId":148,"name":"4"},{"id":152,"parentId":151,"name":"5"}];

const transform = arr => new Map(arr.map((o) => [o.id,o]));

const traverse = (map,id) => {
  const startObj = map.get(+id);
  if("parentId" in startObj)
    return [...traverse(map,startObj.parentId),startObj.parentId]; 
  else
    return [];
}

console.log(traverse(transform(arr),"152"));

如果您想在结果中包含“152”,您可以将递归函数更改为使用 id 参数,并将基本情况更改为返回 [id](注意 {{ id 前面的 1}} 用于将其转换为数字(如果是字符串):

+

,

我将首先使用 reduce

按 id 索引数据
var byId = data.reduce( (acc,i) => {
  acc[i.id] = i
  return acc;
},{});

然后只需使用循环并将 id 推送到结果数组

var item = byId[input];
var result = []
while(item.parentId) {
  result.push(item.parentId)
  item = byId[item.parentId];
}

现场示例:

const input = 152;
const data = [ { "id":1,"name":"root" },{ "id":2,"name":"2" },{ "id":148,"name":"3" },{ "id":151,"name":"4" },{ "id":152,"name":"5" } ]

var byId = data.reduce( (acc,{});

var item = byId[input];
var result = []
while(item.parentId) {
  result.push(item.parentId)
  item = byId[item.parentId];
}
console.log(result.reverse());

,

尝试更改此行

parentsArr.unshift(`${item.parentId}`);

为此

parentsArr.push(`${item.parentId}`);

那就试试

console.log(parentsArr);
,

这就是我的结局。基本上混合了 Janek 和 Nicks 的答案。只需两步:

  1. 将代码转换为地图。
  2. 用一个小函数提取ancester_id

let data = [
    {"id":1,"name":"5"}
];
    
data = data.reduce( (acc,value) => {
  // could optionally filter out the id here
  return acc.set(value.id,value)
},new Map());


function extract_ancestors( data,id ) {
  let result = [];
  while( data.get( id ).parentId ) {
    id = data.get( id ).parentId;
    result.push(id)
  }
  return result;
}

// some visual tests
console.log( extract_ancestors( data,152 )  );
console.log( extract_ancestors( data,148 )  );
console.log( extract_ancestors( data,1 )  );

PS:我的 OOP 倾向从此开始变得很痒,哈哈。