繁体   English   中英

使用索引数组访问和修改 Javascript 中任意深度的嵌套 arrays

[英]Using an array of indices to access and modify arbitrarily deep nested arrays in Javascript

我有一个对象数组。 每个 object 还可以包含对象数组,依此类推到任意深度。

var myArray = [
    { 
        id:'foo', 
        items:[]
    },
    {
        id:'bar', 
        items:[
            {
                id:'blah'
                items:[...etc...]
            }
        ]
    }
]

我想使用索引数组读取、添加和删除嵌套 arrays 中的对象。

因此,将使用以下索引数组作为参数调用 function 以从myArray中删除值myArray[1][3][2][1, 3, 2]

我发现您可以使用reduce()返回一个值,如下所示:

indices.reduce((acc, cur) => Array.isArray(acc) ? acc[cur] : acc.items[cur], myArray)

但无法解决如何使用相同的想法删除或添加值。 任何帮助深表感谢。

最简单的方法是仅使用索引而不使用最后一个索引,以便根据需要将其用于任何操作。

对于删除,您需要此索引来splice数组,以及更新。

在这种情况下,您可以返回父 object 并使用items作为给定数组的属性作为减少的起始值。

这允许访问父 object 并使用items进行任何进一步的操作。

lastIndex = indices.pop();
parent = indices.reduce((r, index) => r.items[index], { items: myArray });

// further use
parent.items.splice(lastIndex, 1); // delete

您可以创建一个 function,它采用类似的 arguments 作为splice function。 使用rest 参数传递嵌套数组、 indices路径、要删除的项目总数并在末尾收集要添加的所有新项目。

function deepSplice(array, indices, deleteCount, ...toBeInserted) {
  const last = indices.pop();
  const finalItems = indices.reduce((acc, i) => acc[i].items, array);
  finalItems.splice(last, deleteCount, ...toBeInserted);
  return array
}
  • indices数组中删除最后一个索引。
  • reduce indices数组以获取每个循环中的嵌套items数组,以获取要对其执行插入/删除操作的最终items数组。
  • 根据传递的参数,在last索引上使用splice来插入/删除。

如果您只想插入,请传递deleteCount = 0 如果您只想删除,请跳过最后一个参数。

这是一个片段:

 const myArray = [ { id: "0", items: [] }, { id: "1", items: [ { id: "1.0", items: [ { id: "1.0.0", items: [] }, { id: "1.0.1", items: [] }] }, { id: "1.1", items: [] } ] } ]; function deepSplice(array, indices, deleteCount, ...toBeInserted) { const last = indices.pop(); const finalItems = indices.reduce((acc, i) => acc[i].items, array); finalItems.splice(last, deleteCount, ...toBeInserted); return array } console.log( // removes "1.0.1" item and inserts a new object there deepSplice(myArray, [1,0,1], 1, { id: 'newlyInserted'}) )

这是使用object-scan的解决方案。

使用对象扫描的主要优点是您可以获得更多控制来调整您的功能(例如,如果您想要获得多个条目或进行模糊键匹配等)。 但是,复杂性增加了,因此需要权衡取舍,具体取决于您的要求。

 // const objectScan = require('object-scan'); const myArray = [{ id: '0', items: [] }, { id: '1', items: [ { id: '1.0', items: [{ id: '1.0.0' }, { id: '1.0.1' }] }, { id: '1.1', items: [] } ] }]; const indicesToNeedle = (indices) => indices.map((idx) => `[${idx}]`).join('.items'); const get = (array, indices) => objectScan( [indicesToNeedle(indices)], { abort: true, rtn: 'value' } )(array); const splice = (array, indices, deleteCount, ...toBeInserted) => objectScan( [indicesToNeedle(indices)], { abort: true, rtn: 'bool', // returns true iff spliced filterFn: ({ parent, property }) => { parent.splice(property, deleteCount, ...toBeInserted); return true; } } )(array); console.log(get(myArray, [1, 0, 1])); // => { id: '1.0.1' } console.log(get(myArray, [1, 0, 2])); // => undefined // removes "1.0.1" item and inserts two objects there console.log(splice(myArray, [1, 0, 1], 1, { id: '1.0.1-new' }, { id: '1.0.2-new' })); // => true console.log(myArray); // => [ { id: '0', items: [] }, { id: '1', items: [ { id: '1.0', items: [ { id: '1.0.0' }, { id: '1.0.1-new' }, { id: '1.0.2-new' } ] }, { id: '1.1', items: [] } ] } ]
 .as-console-wrapper {max-height: 100%;important: top: 0}
 <script src="https://bundle.run/object-scan@13.8.0"></script>

免责声明:我是对象扫描的作者

暂无
暂无

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

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