0

Currently I have an array that I want to sort by 3 keys. For simplicity, the array looks like this:

bArray = [ 
{StartDate:"Mar 1, 2017", ID:"ABC-001", Serial:"10000", Qty: "1"},
{StartDate:"Jun 3, 2017", ID:"CDE-001", Serial:"10004", Qty: "1"}, 
{StartDate:"Mar 1, 2017", ID:"ABC-002", Serial:"10001", Qty: "3"},
{StartDate:"Apr 2, 2017", ID:"CDE-001", Serial:"10003", Qty: "1"},
{StartDate:"Mar 1, 2017", ID:"ABC-001", Serial:"10002", Qty: "1"},
]

I want to sort by ascending in all 3 keys. First by Date, then by ID, then by Serial.

I managed to get it working for Date and ID, however, when I add Serial comparison in the code, I get unexpected results, where the ID and Serial may have anomalies. For example it may be sorted like this when I run the code:

bArray = [ 
{StartDate:"Mar 1, 2017", ID:"ABC-001", Serial:"10000", Qty: "1"},
{StartDate:"Mar 1, 2017", ID:"ABC-002", Serial:"10001", Qty: "3"},
{StartDate:"Mar 1, 2017", ID:"ABC-001", Serial:"10002", Qty: "1"},
{StartDate:"Apr 2, 2017", ID:"CDE-001", Serial:"10003", Qty: "1"},
{StartDate:"Jun 3, 2017", ID:"CDE-001", Serial:"10004", Qty: "1"} 
]

The second and third lines should be reversed because ID should take precedence over Serial.

My code is as follows:

bArray.sort(function (c,d){
  if (c.StartDate > d.StartDate) { return 1; }
  else if (d.StartDate < c.StartDate) { return -1; }

  if (c.ID > d.ID) { return 1; }
  else if (d.ID < c.ID) { return -1; }

  if (c.Serial > d.Serial) { return 1; }
  else if (d.Serial < c.Serial) { return -1; } 
  else { return 0; }
});

I'd like to also mention that the array I'm sorting is over 100+ lines.

Any insight is much appreciated.

Thanks, Vincent

2
  • 4
    Do you realize you are sorting dates via strings, not the date? And the Serial is sorting by strings, not numbers. Commented May 9, 2017 at 15:47
  • Dates work fine - they are Date data types in the real scenario Serial could be a string or a number or a combination of both Commented May 9, 2017 at 15:54

2 Answers 2

2

Your comparisons are all of the form

if ( c.X > d.X ) { return 1; }
else if ( d.X < c.X ) { return -1; }

This will never return -1; if c.X > d.X, then d.X < c.X, but you will have already returned 1.

Instead, you should have c and d in the same order:

if ( c.X > d.X ) { return 1; }
else if ( c.X < d.X ) { return -1; }
// -------^-----^

(Or you could keep them reversed in the else and use > instead of <.)

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

Comments

0

To sort by date you should parse dates, then you can use localeCompare for strings and finally change Serial to numbers.

var arr = [ 
{StartDate:"Mar 1, 2017", ID:"ABC-001", Serial:"10000", Qty: "1"},
{StartDate:"Jun 3, 2017", ID:"CDE-001", Serial:"10004", Qty: "1"}, 
{StartDate:"Mar 1, 2017", ID:"ABC-002", Serial:"10001", Qty: "3"},
{StartDate:"Apr 2, 2017", ID:"CDE-001", Serial:"10003", Qty: "1"},
{StartDate:"Mar 1, 2017", ID:"ABC-001", Serial:"10002", Qty: "1"},
]
arr.sort(function(a, b) {
  return Date.parse(a.StartDate) - Date.parse(b.StartDate) ||
    a.ID.localeCompare(b.ID) || +a.Serial - +b.Serial
});

console.log(arr)

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.