繁体   English   中英

将按ASCII顺序排序的1D数组转换为Javascript中的嵌套数组

[英]Convert 1D array sorted by ASCII order to a nested array in Javascript

假设下面按照ascii顺序按code属性排序的对象数组:

var codes = [
    { code: '01' },
    { code: '0101' },
    { code: '0102' },
    { code: '010201' },
    { code: '0103' },
    { code: '02' },
    { code: '0201' },
    { code: '0202' },
];

如何将其转换为嵌套数组,如下所示:

var nestedCodes = [
    {
        code: '01',
        children: [
            { code: '0101' },
            {
                code: '0102',
                children: [
                    { code: '010201' }
                ]
            },
            { code: '0103' }
        ]
    },
    {
        code: '02',
        children: [
            { code: '0201' },
            { code: '0202' }
        ]
    }
];

代码的结构就像连接多个0NN可以是介于1和9之间的数字。请注意,代码来自服务器,除了title code之外还有一些其他属性,但在这个问题中无关紧要。

这里的主要思想是为jsTree制作一个合适的格式。

您可以使用递归解决方案执行此操作。 我们的想法是维护path (通过带有正则表达式的String.prototype.match作为数组获得)和您希望在每个递归调用下插入codeparent

parent跟踪您要在“当前”递归调用中选择的节点,并且path有助于在您继续深入时构建parent

 function insert(d, path, parent, arr) { if (path.length === 0) { arr.push(Object.assign({}, d)); return; } var target = arr.find(e => e.code === parent); target.children = target.children || []; insert(d, path.slice(1), parent + path[0], target.children); } var codes = [ { code: '01' }, { code: '0101' }, { code: '0102' }, { code: '010201' }, { code: '0103' }, { code: '02' }, { code: '0201' }, { code: '0202' }, ]; var res = codes.reduce((a, c) => { var p = c.code.match(/(0[1-9])/g); insert(c, p.slice(1), p[0], a); return a; }, []); console.log(res); 

当然,假设是在插入code时,之前已经插入了其父code

我努力编写将构建所需结构的递归函数。 这里找到答案

但要做到这一点,您必须首先将parent属性添加到每个codes数组。 我这样做的假设是每个code都有一个父代,它除了最后两个字节之外等同于代码本身。

 var codes = [{code: '01' }, {code: '0101' }, {code: '0102' }, {code: '010201'}, {code: '0103' }, {code: '02' }, {code: '0201' }, {code: '0202' }, ]; // add parents to each code codes.forEach(function(c) { if (c.code.length > 2) { c.parent = c.code.substr(0, c.code.length - 2); } else { c.parent = 'root'; } }); function find_children(arr, parent) { var out = []; for (var i in arr) { if (arr[i].parent == parent) { var children = find_children(arr, arr[i].code); if (children.length) { arr[i].children = children; } out.push(arr[i]) } } return out; } var nested = find_children(codes,'root'); console.log(nested); 

代码有点长,但在我看来很容易理解。 它非常强大 - 不需要对数组进行排序,并且不需要01来处理0102 (如果需要)。 如果不处理这些情况,代码可以更短,但我认为你可能需要这个。

首先,从数据中创建基于对象的树数据结构。 此树具有键和值,并且构建非常有效,因为通过索引访问是O(1)。 接下来,通过遍历基于对象的树,然后将每个图层转换为数组,将基于对象的树转换为最终的基于数组的树数据结构。

我也大量使用递归,因为递归非常适合创建和遍历树。

与其他答案相比,我的算法具有更好的时间复杂度,因为我创建了一个在创建树时具有O(1)访问权限的字典/对象。 其他算法在每个层内进行搜索,这是低效的。 我的算法在O(N)中运行,而此处的其他答案更短但在O(N ^ 2)中运行。

只需将format功能复制到您的代码中即可使用。

 const codes = [ { code: '01' }, { code: '0101' }, { code: '0102' }, { code: '010201' }, { code: '0103' }, { code: '02' }, { code: '0201' }, { code: '0202' }, ]; function format(codes) { // Splits the string into an array of 2-character strings. const SPLIT_REGEX = /.{2}(?=(.{2})+(?!.))|.{2}$/g; const codeFragments = codes.map(obj => obj.code.match(SPLIT_REGEX)); // 1. Represent the data as a tree which is more efficient to build. const tree = {}; function createTree(tree, fragments) { let node = tree; fragments.forEach(fragment => { if (!node[fragment]) { node[fragment] = {}; } node = node[fragment]; }); } codeFragments.forEach(fragments => createTree(tree, fragments)); /* tree will have the structure: { "01": { "01": {}, "02": { "01": {} }, "03": {} }, "02": { "01": {}, "02": {} } } */ // 2. Convert the tree structure into the desired format. function generateCodesFromTree(tree, previous) { const nestedCodes = []; Object.keys(tree).forEach(treeNode => { const code = previous + treeNode; const children = generateCodesFromTree(tree[treeNode], code); const nestedCode = { code }; if (children.length > 0) { nestedCode.children = children; } nestedCodes.push(nestedCode); }); return nestedCodes; } return generateCodesFromTree(tree, ''); } console.log(format(codes)); 

它只能通过使用递归方法来实现。 试试这个吧。

 let codes = [ { code: '01' }, { code: '0101' }, { code: '0102' }, { code: '010201' }, { code: '0103' }, { code: '02' }, { code: '0201' }, { code: '0202' }, ]; roots = codes.filter(c => c.code.length === 2); roots.forEach(c => assign(c)); console.log(roots); function assign(code) { codes.forEach(c => { if (c !== code) { if (code.code === c.code.slice(0, code.code.length)) { code.children = !code.children ? [c] : [...code.children, c]; assign(code.children[code.children.length - 1]); } } }); } 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM