I have an array which contains "Zeros" and I want to move all of the "Zeros" to the last indexes of the array.
The expected output is:
[1,2,3,0,0,0,0]
But instead I get:
[1,2,0,3,0,0,0]
let a = [0, 1, 2, 0, 0, 3, 0];
let count = 0;
let len = a.length;
for (i = 0; i < len; i++) {
if (a[i] == 0) {
count = count + 1;
a.splice(i, 1);
}
}
for (j = 0; j < count; j++) {
a.push(0);
}
console.log(a);
I have an array which contains "Zeros" and I want to move all of the "Zeros" to the last indexes of the array.
The expected output is:
[1,2,3,0,0,0,0]
But instead I get:
[1,2,0,3,0,0,0]
let a = [0, 1, 2, 0, 0, 3, 0];
let count = 0;
let len = a.length;
for (i = 0; i < len; i++) {
if (a[i] == 0) {
count = count + 1;
a.splice(i, 1);
}
}
for (j = 0; j < count; j++) {
a.push(0);
}
console.log(a);
Share
edited Jun 30, 2019 at 19:19
sergdenisov
8,5729 gold badges51 silver badges66 bronze badges
asked Jun 30, 2019 at 18:59
Faizal Mohaideen KadershaFaizal Mohaideen Kadersha
1251 silver badge7 bronze badges
1
- 1 The title seems to suggest you found a bug in a native JavaScript method. Suppress that thought. Convince yourself it is not that method that has the bug, but your code. – trincot Commented Jul 1, 2019 at 21:27
7 Answers
Reset to default 9When you remove the item from the array all the element shift down by one. When you advance your index (i++), you skip the shifted down item in the array which happens to be successive zero in the array.
Solution: Do the for next loop backward and it'll work.
Because splice changes the length of the array, you could iterate from the end of the array and splice the found value directly to the last index.
With this approach, you need only a single loop.
var a = [0, 1, 2, 0, 0, 3, 0],
i = a.length;
while (i--) {
if (a[i] === 0) {
a.splice(a.length, 0, ...a.splice(i, 1));
}
}
console.log(a);
A shorter approach without splicing - and starting from zero.
var a = [0, 1, 2, 0, 0, 3, 0],
i, j = 0;
for (i = 0; i < a.length; i++) {
if (a[i] !== 0) {
[a[j], a[i]] = [a[i], a[j]]; // swap
j++;
}
}
console.log(a);
You can do it much simpler with Array.prototype.sort()
:
const array = [0, 1, 2, 0, 0, 3, 0];
const sortedArray = array.sort((a, b) => {
if (a === 0) {
return 1;
}
if (b === 0) {
return -1;
}
return a - b;
});
console.log(sortedArray);
In the for loop when you splice the array the array and it length are changed.
for that you must fix the i in the for loop by subtract 1
i++;
and fix the length by subtract 1 or reget the length again
let a = [0, 1, 2, 0, 0, 3, 0];
let count = 0;
let len = a.length;
for (i = 0; i < len; i++) {
if (a[i] == 0) {
count = count + 1;
a.splice(i, 1);
len = a.length;
i--;
}
}
for (j = 0; j < count; j++) {
a.push(0);
}
console.log(a);
Instead of splicing the Array over and over again, here is a different approach:
let a = [0, 1, 2, 0, 0, 3, 0];
// create some more (random) data
for (let i = a.length; i < 30; ++i)
a[i] = Math.floor(Math.random() * Math.random() * 10);
console.log(""+a);
let i = 0, j = 0, len = a.length;
// move non-0 values to the front
while (i < len) {
if (a[i] !== 0) {
a[j++] = a[i];
}
++i;
}
// fill the end of the list with 0
while (j < len) a[j++] = 0;
console.log(""+a);
You could add i--;
and len--;
each time you use splice:
let a = [0, 1, 2, 0, 0, 3, 0];
let count = 0;
let len = a.length;
for (i = 0; i < len; i++) {
if (a[i] == 0) {
count = count + 1;
a.splice(i, 1);
i--; len--;
}
}
for (j = 0; j < count; j++) {
a.push(0);
}
console.log(a);
This is because when you splice 1 element, the keys of the array are shifted down by one, so the key of the next element you want to check is the same as the one you just removed. The len is also corrected with len--;
because we just removed an element.
While this answer is the correct way of doing this using your original plan, it is kind of a fix. Your problem was that you loop over an array, and that array loses elements during the loop, and generally the right approach in these situations is to loop backward. This way the elements that risks having their key changed during the loop are the elements we already checked.
Note that each call to splice
has generally O(n) plexity. There are many ways to instead achieve your desired result an order of magnitude more efficiently with a single O(n) iteration. Here's one:
let a = [0, 1, 2, 0, 0, 3, 0]
for (let i=0, j=0; j<a.length; j++)
if (a[j] && i != j)
[a[i++], a[j]] = [a[j], 0]
console.log(a)
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1743679095a4489070.html
评论列表(0条)