例如,我有一个数组:[1,1,2,2,2,3,4,4,4],我想要一个结果,将相同的相邻对象分组到另一个数组中:[[1,1],[2,2,2],[3],[4,4,4]],我怎么能这样做呢?我试过:
const arr=[1,1,2,2,2,3,4,4,4];
const result=[];
for(let i=0,j=1;j<arr.length;j++){
if(arr[j-1]!=arr[j]){
result.push(arr.slice(i,j));
i=j;
}
}
document.write(JSON.stringify(result));
“我不知道,我也不知道。
我也试
const arr=[1,1,2,2,2,3,4,4,4];
const result=[];
for(let i=0,j=1;j<arr.length;j++){
if(arr[j-1]!=arr[j] || j==arr.length-1){
result.push(arr.slice(i,j));
i=j;
}
}
document.write(JSON.stringify(result));
但结果是[[1,1],[2,2,2],[3],[4,4]],在最后一组中漏掉了一个“4”。
我该怎么修复它?
8条答案
按热度按时间eufgjt7s1#
你不是在和最后一组打交道。你的想法显然是当你发现一个与前一个元素不同的元素时,推送最后一个组(由从i,included到j,excluded的所有元素组成)。
但最后一组没有与前一组不同的追随者。
有办法解决的。例如
基于
||
是一个惰性或的事实。所以如果j
是arr.length
,那么arr[j-1]!=arr[j]
就不会被计算。这避免了使用索引越界。即使如此,在JavaScript中,这也不是什么大不了的事情:那么arr[j]
将只是undefined
,这对我们来说是可以的,除非arr[j-1]
也是,也就是说,除非undefined
是arr
内容的可能值。你也可以简单地在循环之后,在最后一个
i
之后添加所有东西(但是你需要i
存在于循环之外,所以let i=0
在循环之前完成)。我不会花太多时间在这上面,我相信你会有很多方法来完成这项任务。我主要想指出的是另一种可能性,取自 “计算机编程的艺术”,并且经常被忽视:一个哨兵。
由于您的问题是最后一个组没有后继者的特殊情况,只需添加一个后继者。
当然,这意味着改变
arr
。因此,这并不总是可行的。但是这样就避免了在每次迭代中测试j==arr.length
的成本。同样,这也是可以避免的,通过在群体之后处理特殊情况。所以,我并不是说哨兵是唯一的选择,也不是说它是更快的一个。只是,值得被人知道。正如您所看到的,只需要一行代码(添加sentinel),我就可以保持您的代码不变。请注意,更简单的解决方案(Marc在注解中给出的解决方案),即只让
j
包含arr.length
,这是隐含的版本:JavaScript中的数组在所有元素后都有隐式的undefined
。所以,如果像我的whateveraslongasitisnot4
,undefined
在数组中找不到,特别是在最后,那么,隐式的undefined
就像一个哨兵。我不确定是不是这么想的,但这是一种看待它的方式。brgchamk2#
Simple One Liner,你可以使用下面的代码来得到你想要的结果。
vs91vp4v3#
如果当前元素与前一个索引中的元素不同,则创建一个新的子数组。
然后,将当前元素推入最近创建的子数组。
0s7z1bwu4#
你必须检查所有的
array elements
一个接一个的数组组。如果要检查
current
元素是否与previous
元素相同,请执行以下代码:zi8p0yeb5#
你可以取一个optional chaining operator
?.
并检查最后一个数组是否存在值。23c0lvtd6#
最快的方法是像在第二个代码片段中那样对数组进行切片。为了包含最新的项,我更喜欢在循环后切片最新的块。因为你不需要在循环中检查最新的块,所以它会更快一点。
fhg3lkii7#
作为一个班轮:
ctehm74n8#
你可以使用
reduce
和Array.prototype.at
来得到结果。