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



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

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

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

因此,将调用一个用于从myArray中删除值myArray[1][3][2]的函数,并将使用此索引数组作为参数:[1, 3, 2]

我发现您可以使用reduce()返回如下值:

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

但无法弄清楚如何使用相同的想法删除或添加值。任何帮助都非常感谢。

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

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数组中删除最后一个索引。
  • reduceindices数组以获取每个循环中的嵌套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'})
)

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

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

在这种情况下,您可以返回父对象,并使用具有items作为给定数组属性的对象作为归约的起始值。

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

lastIndex = indices.pop();
parent = indices.reduce((r, index) => r.items[index], { items: myArray });
// further use
parent.items.splice(lastIndex, 1); // delete

这是使用对象扫描的解决方案。

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

// 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>

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

最新更新