Javascript 节点-访问多维数组的最后一个索引
我有一个问题,我认为是直截了当的,但我看到了相互矛盾的答案 假设我有以下数据结构:Javascript 节点-访问多维数组的最后一个索引,javascript,node.js,arrays,Javascript,Node.js,Arrays,我有一个问题,我认为是直截了当的,但我看到了相互矛盾的答案 假设我有以下数据结构: const data = [ ..., { someKey: [ ..., { someDeepKey: [ ..., 'two' ], } ] } ] 因此,访问以下所有内容的第一个索引如下所示: data[0].someKey[0].someDeepKey[0] 但是如果我
const data = [
...,
{
someKey: [
...,
{
someDeepKey: [
...,
'two'
],
}
]
}
]
因此,访问以下所有内容的第一个索引如下所示:
data[0].someKey[0].someDeepKey[0]
但是如果我想找到所有这些的最后一个索引,我还没有找到一个干净的方法。我看到一些人建议扩展阵列原型本身,我觉得这是个坏主意
我唯一能想到的另一个“干净”的解决方案是将变量链接起来,使其具有半可读性
let someKey = data[data.length - 1].someKey
let someDeepKey = someKey[someKey.length - 1].someDeepKey
let someDeepKeyValue = someDeepKey[someDeepKey.length - 1]
有人能提出一个更干净的方法来做这件事吗?我相信Python支持一些整洁的东西,例如:
data[-1].someKey[-1].someDeepKey[-1]
我想知道JS中是否有类似的东西。我碰巧发现了这一点。它似乎可以在不改变原始数组的情况下执行我想要的操作,比执行整个
.length-1
链要干净得多:
let data = [
{
someKey: [
{
someOtherKey: [
'Fake',
'Name'
]
}
]
}
];
let name = data.slice(-1).pop()
.someKey.slice(-1).pop()
.someOtherKey.slice(-1).pop();
console.log(name) // 'Name'
console.log(data) // Original data
不确定它的性能如何,但它肯定至少更具可读性,并且它抓住了所需的最终值
这可能是一场性能噩梦,因为它在内存中创建了如此多的副本,但当我们只处理较小的数据集时,我认为这符合在深度嵌套的数组中捕获精确值而不改变任何内容的要求
进行了一些评估。以下是一些基本测试:
//构建数据集
设dataSet=[];
for(设i=0;i<100;i++){
让someObj={
someKey:[]
}
对于(设j=0;j<100;j++){
让另一个对象={
someOtherKey:[]
}
for(设k=0;k<1000;k++){
someOtherObj.someOtherKey.push(k)
}
someObj.someKey.push(someOtherObj)
}
dataSet.push(someObj)
}
常量slicePop=(数据)=>{
//切片汽水
让start=window.performance.now();
让name=data.slice(-1).pop()
.someKey.slice(-1).pop()
.someOtherKey.slice(-1.pop();
让end=window.performance.now();
让时间=结束-开始;
返回时间
}
常量spreadPop=(数据)=>{
//传播流行音乐
让start=window.performance.now();
让name=[…[…[…]数据].pop().someKey].pop().someOtherKey].pop()
让end=window.performance.now();
让时间=结束-开始;
返回时间
}
常量lastMethod=(数据)=>{
//作用
让start=window.performance.now();
常量last=(arr)=>arr[arr.length-1]
让name=last(last(last(data).someKey.someOtherKey)
让end=window.performance.now();
让时间=结束-开始;
返回时间
}
常量变量=(数据)=>{
让start=window.performance.now();
让someKey=data[data.length-1].someKey
让someOtherKey=someKey[someKey.length-1].someOtherKey
让name=someOtherKey[someOtherKey.length-1]
让end=window.performance.now();
让时间=结束-开始;
返回时间
}
常量lastdeph=(arr)=>{
让start=window.performance.now();
让name=['someKey','someOtherKey',''。减少(
(最后,cur)=>(
(res=last[last.length-1]),
res[cur]?res[cur]:未定义
),arr)
让end=window.performance.now();
让时间=结束-开始;
返回时间
}
设时间=[];
设spreadPopTimes=[];
设lastMethodTimes=[];
设variablesTimes=[];
让还原时间=[];
for(设i=0;i<100;i++){
slicePopTimes.push(slicePop(数据集))
}
for(设i=0;i<100;i++){
spreadPopTimes.push(spreadPop(数据集))
}
for(设i=0;i<100;i++){
lastMethodTimes.push(lastMethod(数据集))
}
for(设i=0;i<100;i++){
variablesTimes.push(变量(数据集))
}
for(设i=0;i<100;i++){
reduceTimes.push(lastdeph(数据集))
}
常量getAvg=(arr)=>{
让总数=平均减少((acc,i)=>{
acc+=i
返回acc
}, 0);
返回((总/到达长度)*1000)
}
让结果={
slicePopTime:getAvg(slicePopTimes),
spreadPopTime:getAvg(spreadPopTimes),
lastMethodTime:getAvg(lastMethodTimes),
variablesTime:getAvg(variablesTimes),
还原时间:getAvg(还原时间)
}
log('RESULTS',RESULTS)
您可以遵循以下代码
let x = [...[...[ ...data ].pop().someKey].pop().someDeepKey].pop()
定义一个名为last的函数来获取数组的最后一个元素,并像这样使用它
last(last(last)(data).someKey.someDeepKey)
这里使用reduce
的小util非常方便,可以用于任何级别的嵌套
const数据=[
{
someKey:[
{
someDeepKey:[“一”],
},
],
},
{
someKey:[
{
someDeepKey:[“一”,“二”],
},
],
},
];
const lastdeph=[“someKey”,“someDeepKey”,““”]。减少(
(last,cur)=>((res=last[last.length-1]),res[cur],
数据
);
console.log(lastDeep)据我所知,目前还没有简单的方法可以做到这一点,但您可能会感兴趣。它目前处于第三阶段,我想很快就会被标准化。虽然我没有提到它,但这确实改变了原始数据,对吗?我想这是我想要避免的一个副作用。不,你的数组没有改变哦,我明白了,因为你在传播它,你也在内存中复制。我认为如果你的数组有大量元素,这将是一个代价高昂的操作,但我认为它是干净的,因为你想要一种干净的方式:)有趣的是,将运行超过10000000个索引的两个操作平均100次表明,您的操作速度大约是原来的两倍。我永远无法理解reduce
我认为这是一个聪明的解决方案,但它的速度非常慢。对于100*100*1000的多维数组。。。。查找时间为:lastMethodTime:0.749sec缩减时间:1.349sec切片时间:1.050sec扩展时间:0.949sec变量时间:0.549sec