如何在深度未知的数组内递归构建子数组的路径

时间:2017-11-23 19:16:43

标签: javascript jquery arrays recursion

我有一个如下结构的数组:

var persons= [{name: 'John',
               id: 1,
               children :[{name :'John Jr',
                           id: 11,
                           children :[{name: 'John Jr Jr'
                                      id: 111}]
                          },
                          {name :'Jane'
                           id: 12}]
             },
             {name:'Peter',
              id :2
             },
             ...]

它基本上是一个对象数组,对象是人,每个人可能有任意数量的后代,这些后代由他们自己的人物对象组成。每个人的后代数量都是未知的。

我想要实现的是以这种方式构建地图:

var personsMap =[1 : 'John',
            11: 'John > John Jr',
            111 : 'John > John Jr > John Jr Jr',
            12: 'John > Jane',
            ...
           ]

这是每个路径的每个可能组合的地图,因此通过按人的身份查询地图,它应该返回它的父母>的字符串。祖父母> ...

我正在尝试递归地构建这个地图,所以到目前为止我尝试过:

var personsMap = {};

function buildParentsMap (persons){
   $.each (persons, function(ndx, person){
      if(person.children && person.children.length > 0){
          buildParentsMap(person.children);
      }
      personsMap[person.id] = person.name; 
   });
   console.log(personsMap);
}

但是这会输出以下内容:

[1 : 'John',
11: 'John Jr',
111 'John Jr Jr',
12: 'Jane',
...]

这是所有的名字,但没有按照我上面解释的方式连接。 我怎样才能做到这一点?感谢

2 个答案:

答案 0 :(得分:1)

您可以使用此版本的功能(ES6代码):



function buildParentsMap(persons, path = []) {
    return (persons || []).reduce( (acc, person) =>
            acc.concat({ [person.id]: path.concat(person.name).join(' > ') },
                       buildParentsMap(person.children, path.concat(person.name)))
        , []);
}
// Sample data
const persons=[{name: 'John',id: 1,children : [{name :'John Jr',id: 11,children :[{name: 'John Jr Jr',id: 111}]}, {name :'Jane',id: 12}]}, {name:'Peter', id :2 }];

const result = buildParentsMap(persons);
console.log(result);

.as-console-wrapper { max-height: 100% !important; top: 0; }




答案 1 :(得分:1)

原始buildParentsMap函数的问题在于,尽管它成功地进行了递归调用以将每个人添加到地图中,但它并没有以任何方式构建以跟踪每个孩子的祖先。在buildParentsMap上调用John Jr Jr时,它只知道有关已传入其中的特定数组的信息,如下所示:[{name: 'John Jr Jr', id: 111}]

解决此问题的一种方法是向buildParentsMap函数添加第二个参数,以跟踪需要将哪些祖先(如果有)添加到当前添加到地图的任何人身上。例如:

var personsMap = {};

// Accept an optional "ancestors" argument in each function call
// so we know what prefix to append onto each child
function buildParentsMap (persons, ancestors){
    // If no ancestors, nothing needs to be appended
    // so set to empty string
    if( !ancestors ) ancestors = "";

    // Loop through all people in the array
    for(let idx in persons){

        let person = persons[idx];

        if(person.children && person.children.length > 0){
            // If this person has children, make a recursive call on the
            // children. Include the current person as an ancestor
            let prefix = ancestors + person.name + " > ";
            buildParentsMap(person.children, prefix);
        }

        personsMap[person.id] = ancestors + person.name;
    }
}

如果我们使用您的示例数组测试它:

var personsExample = [
    { name: 'John',
      id: 1,
        children: [
            {
                name: 'John Jr',
                id: 11,
                children: [
                    {
                        name: 'John Jr Jr',
                        id: 111
                    }
                ]
            },
            {
                name: 'Jane',
                id: 12
            }
        ]
    },
    {
        name:'Peter',
        id: 2
    }
];

buildParentsMap(personsExample);
console.log(personsMap);

输出现在如下所示:

{ 1: 'John',
  2: 'Peter',
  11: 'John > John Jr',
  12: 'John > Jane',
  111: 'John > John Jr > John Jr Jr' }