2

There are quite a few question related to the topic, but I couldn't find the right solution for my case.

var arr = [a, b, null, d, null]

and am sorting this Array with below logic

return function(a,b){ 

    if(a === null){
      return 1;
    }
    else if(b === null){
      return -1;
    }
    else if(a === b){
      return 0;
    }
    else if(ascending) {
      return a < b ? -1 : 1;
    }
    else if(!ascending) {
      return a < b ? 1 : -1;
    }
  };

I get the following outputs for

Ascending : [a, b,  d, null,null]

Descending : [d, b,  a, null,null]

Expected : [null, null,d, b,  a]

What am I doing wrong?

1
  • Your comparison to null does not rely on ascending variable value. PS: it's ugly and confusing when a comparison function is not pure. Commented Nov 13, 2015 at 2:27

3 Answers 3

8

function getSort (ascending) {
  // if ascending, `null` will be pushed towards the end of the array by returning 1
  var nullPosition = ascending ? 1 : -1
  return function (a, b) {
    // if a is null, push it towards whichever end null elements should end up
    if (a == null) return nullPosition
    
    // Note: at this point, a is non-null (previous if statement handled that case).
    //
    // If b is null, it must therefore be placed closer to whichever end the null
    // elements should end up on. If ascending, null elements are pulled towards
    // the right end of the array. If descending, null elements are pulled towards
    // the left.
    //
    // Therefore, we return -nullPosition. If ascending, this is -1, meaning a comes
    // before b; if descending, this is 1, meaning a comes after b. This is
    // clearly the correct behavior, since ascending will push b, which is null,
    // towards the end of the array (with -1) and descending will push b towards
    // the beginning of the array.
    if (b == null) return -nullPosition

    // OTHERWISE, both elements are non-null, so sort normally.
    // if a < b AND
    //     if ascending, a comes first, so return -1 == -nullPosition
    //     if descending, a comes after, so return -nullPosition == -(-1) == 1
    if (a < b) return -nullPosition

    // return the opposite of the previous condition
    if (a > b) return nullPosition
    
    // return 0 if both elements are equal
    return 0
  }
}

function write (arr) { arr.forEach(function (d) { document.write(d + "<br>")})}

var toSort = ['a', 'b', null, 'd', null]

var sortA = getSort(true)
var sortD = getSort(false)

document.write("<br>ASCENDING<br>")
write(toSort.sort(sortA))

document.write("<br>DESCENDING<br>")
write(toSort.sort(sortD))

Sign up to request clarification or add additional context in comments.

2 Comments

what if both rows are null ?
@Tharun then either can come first, so if (a == null) return nullPosition will handle that case.
0

You could use a two pass approach by checking null values first and then order by string.

To change the sort order, you could swap the parameters or use a negated result of the one of the function.

var data = ['a', 'b', null, 'd', null];

// ascending
data.sort(function (a, b) {
    return (a === null) - (b === null) || ('' + a).localeCompare(b);
});
console.log(data);

// descending
data.sort(function (a, b) {
    return (b === null) - (a === null) || ('' + b).localeCompare(a);
});
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

0

What about the below solution?

var arr = [null, 'e', 'a', 'b', null, 'd', null];

function sortBy(arr, ascending) {
    return arr.sort((a, b) => {
        if(!a) return ascending ? 1 : -1;
        if(!b) return ascending ? -1 : 1;
        if (ascending) return a > b ? 1 : -1;
        return a > b ? -1 : 1;
    })
}

const ascendingArr = sortBy(arr, true);
console.log(ascendingArr);
const decendingArr = sortBy(arr, false);
console.log(decendingArr);

Comments

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.