【问题标题】:How to recursively build the path of sub-arrays inside an array with unknown depth如何在深度未知的数组内递归构建子数组的路径
【发布时间】:2018-05-07 19:29:23
【问题描述】:

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

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',
            ...
           ]

它是每条路径的每个可能组合的映射,所以通过人的id查询映射,它应该返回它的父>祖父>...

的字符串

我正在尝试以递归方式构建此地图,所以到目前为止我已经尝试过:

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',
...]

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

【问题讨论】:

  • 编号系统只是一个例子,便于理解问题。在我的真实情况下,ID 以不同的方式生成。
  • 在否决投票之前,您是否至少完整阅读了这个问题?我完全看不出与复制品有什么共同之处

标签: javascript jquery arrays recursion


【解决方案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 清晰)
【解决方案2】:

原始buildParentsMap 函数的问题在于,尽管它成功地进行递归调用以将每个人添加到地图中,但它并没有以任何方式构建来跟踪每个孩子的祖先。当buildParentsMapJohn 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' }

【讨论】:

  • 感谢您的帮助,第一个答案已经解决了我的问题。 +1 对于解释,这让我的头脑更清楚了!
  • 没问题!很高兴增加一些清晰度! :)
猜你喜欢
  • 1970-01-01
  • 2013-11-30
  • 1970-01-01
  • 2012-04-18
  • 2010-10-31
  • 2020-04-14
  • 2023-01-28
  • 2017-05-09
  • 2021-10-09
相关资源
最近更新 更多