24

I have an array of objects:

var arr = [
  {title:'50 - 50'},
  {title:'100 - 100'},
  {title:'50 - 65'},
  {title:'100 - 125'}
];

I'm attempting to sort this array so that the items appear in the following order:

var arr = [
  {title:'50 - 50'},
  {title:'50 - 65'},
  {title:'100 - 100'},
  {title:'100 - 125'}
];

Currently I'm using the following sorting function to attempt this:

arr.sort(function(a, b){
  var titleA = a.title;
  var titleB = b.title;
  var arrA = titleA.split(' - ');
  var arrB = titleB.split(' - ');
  var keyA = parseInt(arrA[0]), 
      keyB = parseInt(arrB[0]);

  // Compare the 2 keys
  if(keyA < keyB) return -1;
  if(keyA > keyB) return 1;
  return 0;
});

However, this returns the items in the following order:

var arr = [
  {title:'50 - 65'},
  {title:'50 - 50'},
  {title:'100 - 125'},
  {title:'100 - 100'}
];

It looks like I need to sort by the first number in the title and then the second number. Any ideas?

2
  • use the code sample instead of code snippet when you are sharing the code. use code snippet whenever you are running it. Commented Feb 17, 2015 at 11:23
  • You are sorting on the first number only. Add another criterium for the second number when keyA == keyB. Commented Feb 17, 2015 at 11:28

5 Answers 5

38

Here is a cleaner and shorter version that does not require a bunch of nested if/else cases:

const sorted = arr.sort((a,b) => {

    const [a1, a2] = a.title.split(' - ').map(Number);
    const [b1, b2] = b.title.split(' - ').map(Number);

    return a1 - b1 || a2 - b2;

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

1 Comment

By far the simplest and cleanest solution here. It works because when a and b are the same, the value is zero, which means it moves on to the next OR operand, and so on.
20

Try this:

arr.sort(function(a, b){
  var titleA = a.title;
  var titleB = b.title;
  var arrA = titleA.split(' - ');
  var arrB = titleB.split(' - ');
  var keyA1 = parseInt(arrA[0]), keyA2 = parseInt(arrA[1]) 
      keyB1 = parseInt(arrB[0]), keyB2 = parseInt(arrB[1]);

  // Compare the 2 keys
  if (keyA1 < keyB1) return -1;
  if (keyA1 > keyB1) return 1;
  if (keyA2 < keyB2) return -1;
  if (keyA2 > keyB2) return 1;
  return 0;
});

3 Comments

Thanks Alex. Works a treat.
Can't understand completely how it works, but surely does work. Will look up the docs. Thanks!
@Alex Kopachov can you help here please : stackoverflow.com/questions/74928718/…
14

In pseudocode, the logic would be the following:

Procedure: comparator(a,b)

  1. If a < b then return -1
  2. If a = b then call comparator(a1, b1) recursively, where a1 and b1 are the comparable values of the next level in the sorting.
  3. If a > b then return 1

In your concrete case, you can do simply do it by modifying your code a bit:

if (keyA < keyB) {
    return -1;
} else if (keyA > keyB) {
    return 1;
} else { // keyA == keyB
    if (titleA < titleB) {
        return -1;
    } else if (title > titleB) {
        return 1;
    } else {
        return 0;
    }
}

1 Comment

+1 for pseudocode and the actual crux: on comparison equality, compare at next level.
1

Create a compare function similar to this:

arr.sort(function(a, b){
  var titleA = a.title;
  var titleB = b.title;
  var arrA = titleA.split(' - ');
  var arrB = titleB.split(' - ');
  var keyA1 = parseInt(arrA[0]), 
      keyA2 = parseInt(arrA[1]),
      keyB1 = parseInt(arrB[0]),
      keyB2 = parseInt(arrB[1]),

  // Compare the 2 keys
  if(keyA1 < keyB1) return -1;
  if(keyA1 > keyB1) return 1;
  else
  {
      if(keyA2 < keyB2) return -1;
      if(keyA2 > keyB2) return 1;
      return 0;
});

Comments

0

Another possibility is to compose a sort function based off of multiple comparator functions. Here is an example function that would do this:

function makeMultiCriteriaSort (...criteria) {
  return (a, b) => {
    for (let i = 0; i < criteria.length; i++) {
      const curCriteriaComparatorValue = criteria[i](a, b)
      // if the comparison objects are not equivalent, return the value obtained
      // in this current criteria comparison
      if (curCriteriaComparatorValue !== 0) {
        return curCriteriaComparatorValue
      }
    }
    return 0
  }
}

// sort an array with multiple criteria
arr.sort(makeMultiCriteriaSort(comparator1, comparator2))

The npm package thenby takes this idea to the next level.

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.