Vincent Hoang
Vincent Hoang

Reputation: 1

Sorting by 3 keys - Javascript

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

Upvotes: 0

Views: 110

Answers (2)

Nenad Vracar
Nenad Vracar

Reputation: 122077

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)

Upvotes: 0

Scott Hunter
Scott Hunter

Reputation: 49883

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 <.)

Upvotes: 2

Related Questions