0

I get a list of elements given as parameter, this is input.

JSON.stringify(moveZeros([1,2,0,1,0,1,0,3,0,1]))

Script should move zeros to the end without changing other elements order. My solution would looks like this code:

var moveZeros = function (arr) {
  var args = Array.prototype.slice.call(arguments);

  for(var i=0; i<args.length; i++) {
        if (args[i] == 0)
           args.splice(i);
           args.push(0);
  }

  console.log(args);

  return args;
}

This should append element's with zero value and append a new, 0 value to end of array. It only prints original array without modification.

plaidshirt
  • 5,189
  • 19
  • 91
  • 181

6 Answers6

2

You had some brackets wrong and missed some arguments. Also you are using an array as the parameter, no need to slice the arguments. You also missed the number of elements for the splice

This does not work for something like [9, 0, 9, 1, 2, 1, 1, 3, 1, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0] (see update further below)

// DOES NOT WORK
var moveZeros = function (arr) {

    for (var i = 0; i < arr.length; i++) {
        if (arr[i] == 0) {
            arr.splice(i, 1);
            arr.push(0);
        }
    }

    console.log(arr);

    return arr;
}

Working solution

    var moveZeros = function(args) {
        var r = [];
        var zeros = 0;
        for (var i = 0; i < args.length; i++) {
            if (args[i] !== 0) {
                r.push(args[i]);
            } else zeros++
        }
        r = r.concat(Array(zeros).fill(0))
        console.log(r);
        return args;
    }
    JSON.stringify(moveZeros([9, 0, 9, 1, 2, 1, 1, 3, 1, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0]));
raphaëλ
  • 6,393
  • 2
  • 29
  • 35
2

It is because arguments is all the arguments passed in. You should be using arr and not arguments.

var moveZeros = function (arr) {
  var args = arr;
  ...
}

Also another issue you will face is when you loop from the start to the end and you move elements to the end, you will be skipping indexes as stuff slides down to fill in the hole that you just created. You should be using reduce() or loop from the end to the start if you are using a for loop.

var moveZeros = function(arr) {
  var args = arr;
  for (var i = args.length - 1; i >= 0; i--) {
    if (args[i] === 0) {
      args.splice(i, 1);
      args.push(0);
    }
  }
  return args;
}

console.log(JSON.stringify(moveZeros([1, 2, 0, 1, 0, 1, 0, 3, 0, 1])));
epascarello
  • 204,599
  • 20
  • 195
  • 236
2

You could use the copy of arr and use a variable for the length check. If a zero is found, the length variable is decremented and the zero is pushed to the end. If not found, the index is incremented.

var moveZeros = function (arr) {
    var args = arr.slice(),
        i = 0,
        l = args.length;

    while (i < l) {
        if (args[i] === 0) {
            args.push(args.splice(i, 1)[0]);
            l--;
        } else {
            i++;
        }
    }
    return args;
}

console.log(moveZeros([1, 2, 0, 1, 0, 1, 0, 3, 0, 1]));

Or use a loop from the end.

var moveZeros = function (arr) {
    var args = arr.slice(),
        i = args.length;

    while (i--) {
        if (args[i] === 0) {
            args.push(args.splice(i, 1)[0]);
        }
    }
    return args;
}

console.log(moveZeros([1, 2, 0, 1, 0, 1, 0, 3, 0, 1]));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

You have to provide count of values to be removed in splice() method.

Also push 0 only if the value was 0. You are pushing it everytime. (Hint: Because the push statement is not in if).

With a copy of array :

You can maintain a new array and push only non zzero values on to it and later push all the zeros. Simple to understand.

var moveZeros = function(args) {
  var arr = [], zCount = 0;
  for (var i = 0; i < args.length; i++) {
    args[i] == 0 ? zCount++ : arr.push(args[i]);
  }
  while (zCount-- > 0) arr.push(0);
  console.log(arr);
  return arr;
}
JSON.stringify(moveZeros([9, 0, 0, 0, 9, 1, 2, 1, 1, 3, 1, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0]));

With reverse loop : You need a reverse loop because every time when you splice you skip an index so repeated 0s will not be removed.

var moveZeros = function(args) {
  for (var i = args.length; i > 0; i--) {
    if (args[i] == 0) {
      args.splice(i, 1);
      args.push(0);
    }
  }
  console.log(args);
  return args;
}
JSON.stringify(moveZeros([9, 0, 0, 0, 9, 1, 2, 1, 1, 3, 1, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0]));
Himanshu Tyagi
  • 5,201
  • 1
  • 23
  • 43
1

I think this would be the funniest way and nicest as line of code and as it's using built-in function (sort) then it faces less performance issues.

var array = [1, 2, 0, -1, 0, 1, 0, 3, 0, 1]
array.sort(a => a === 0);
console.log(array);
Morteza Tourani
  • 3,506
  • 5
  • 41
  • 48
0

first its bad to modify an array while you iterate over it. this can cause some weird jumping that will be confusing. say you have 1,0,0,1 in your loop when you get to index one it will splice and append the zero to the end of the array 1,0,1,0 but the counter will then increment to 2 and it will miss the 0 which is now at position 1.

It looks like youre trying to create a shallow copy with

var args = Array.prototype.slice.call(arguments);

but I am not really sure. I wouldn't modify the array you want to return but rather create some temp array and loop through the input, if its 0 up some counter, if its not 0 push it to the holding array, then push on as many 0s as the counter tells you to and return the temp array

Jake
  • 402
  • 1
  • 4
  • 12