3

I am trying to sort an array so that all the zeros are at the end. However, I don't want the list to be numerically sorted, all the numbers above zero should stay in the same order. Here's what I've got so far:

function placeZerosAtEnd(arr) {
    return arr.sort(compareForSort);
}
function compareForSort(first, second) {
    return first == 0 ? 1 : 0;
}
placeZerosAtEnd([9,0,9,1,0,2,0,1,1,0,3,0,1,9,9,0,0,0,0,0]);

This should return [9,9,1,2,1,1,3,1,9,9,0,0,0,0,0,0,0,0,0,0], but actually returns [3,9,9,1,9,2,9,1,1,1,0,0,0,0,0,0,0,0,0,0]. The zeros are correct, but the other numbers are in a strange order. What is going on here?

http://jsfiddle.net/v67fx4zk/

3
  • i guess its because of quicksort ("divide and conquer") so its a sort algorithms behavior. Commented Sep 23, 2014 at 23:17
  • You could do xs.filter(isntZero).concat(xs.filter(isZero)) Commented Sep 23, 2014 at 23:18
  • I get the expected result with your fiddle. Did you try also handling the case where second is 0 ? Commented Sep 24, 2014 at 10:49

7 Answers 7

11

As other have said, using .sort() was wrong in this instance. This is the code I used in the end, as suggested by elclanrs in the comments below my initial post.

function placeZerosAtEnd(arr) {
    return arr.filter(isntZero).concat(arr.filter(isZero));
}
function isntZero(element) {
    return element > 0;
}
function isZero(element) {
    return element == 0;
}
Sign up to request clarification or add additional context in comments.

Comments

3

The trivial solution with sort: "bubble down" zeros against non-zeros:

[9,0,9,1,0,2,0,1,1,0,3,0,1,9,9,0,0,0,0,0].sort((a, b) => {
  if (a !== 0 && b === 0) return -1;
  if (a === 0 && b !== 0) return 1;
  return 0;
})

// [9, 9, 1, 2, 1, 1, 3, 1, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Comments

2

I don't think you can accomplish this with the sort function. Depending on the sort method the browser uses (quicksort, merge sort, etc.), the sort function works by swapping items into place. So there's no telling where the non-zeroes will end up ... your algorithm simply ensures that they'll appear before the 0s.

Here's a function that will accomplish what you're trying:

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

Comments

2

you can use this some way too

let listSort = [9, 0, 9, 1, 0, 2, 0, 1, 1, 0, 3, 0, 1, 9, 9, 0, 0, 0, 0, 0],
    isntZero = [],
    isZero = []

for (let i = 0; i < listSort.length; i++) {
  if (listSort[i] == 0)
    isZero.push(listSort[i])
  else
    isntZero.push(listSort[i])
}

let output = isntZero.concat(isZero)

console.log(JSON.stringify(output))

Comments

0

In your example the sort function is doing exactly what it's meant to.

You're expecting a stable sort, but a stable sort is not guaranteed by the javascript sort algorithm.

See this question for a discussion on stable sorting in javascript.

Comments

0

You can use arr.sort to solve this problem

reference: Array.sort

   function placeZerosAtEnd(arr) {

     arr.sort(function(key1,key2) {

      if (key1 == 0 ) return 1;
      return -1;
    });    
    return arr;
  }

Comments

-2
arr.sort((a,b) => a - b).reverse()

1 Comment

Why not just do b - a and so remove the need for the .reverse()?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.