Home > Software engineering >  Sort/order a string array by two conditions (name sequence and date)- JavaScript
Sort/order a string array by two conditions (name sequence and date)- JavaScript

Time:03-09

Having some issues trying to sort/order this string array. There are thousands of files names that come back in the response, below is an example of 10.

array = [
'ORDERHEADER_010122.arc',
'ORDERITEM_010122.arc',
'ORDERDETAIL_010122.arc',
'ORDERDETAIL_010222.arc',
'ORDERDETAIL_010322.arc',
'ORDERHEADER_010222.arc',
'ORDERHEADER_010322.arc',
'ORDERHEADER_010422.arc',
'ORDERITEM_010222.arc',
'ORDERDETAIL_010422.arc'
];

A simple array.sort() takes care of half of the issue as it will alphabetize the strings and inherently sort the dates.

What am needing is a "sequence" order of sorts along with the date order. So prioSequence = ['ORDERHEADER', 'ORDERDETAIL', 'ORDERITEM']; would be the sequence I want to see.

Expected output as:

array = [
'ORDERHEADER_010122.arc',
'ORDERDETAIL_010122.arc',
'ORDERITEM_010122.arc',
'ORDERHEADER_010222.arc',
'ORDERDETAIL_010222.arc',
'ORDERITEM_010222.arc',
'ORDERHEADER_010322.arc',
'ORDERDETAIL_010322.arc',
'ORDERHEADER_010422.arc',
'ORDERDETAIL_010422.arc'
];

Any help/guidance would be greatly appreciated! Thanks!

CodePudding user response:

Prefix the string with the parts that determine the sort, i.e. yymmdd and 2 letters from the "ORDER" string, as it turns out that when you pick the 7th and 8th letter of those words (EA, ET, TE), they will be sorted correctly. Then after having sorted the items, remove that prefix again.

Here is how that works out:

let array = [
  'ORDERHEADER_010122.arc',
  'ORDERITEM_010122.arc',
  'ORDERDETAIL_010122.arc',
  'ORDERDETAIL_010222.arc',
  'ORDERDETAIL_010322.arc',
  'ORDERHEADER_010222.arc',
  'ORDERHEADER_010322.arc',
  'ORDERHEADER_010422.arc',
  'ORDERITEM_010222.arc',
  'ORDERDETAIL_010422.arc'
];

let sorted = array.map(item => 
    item.replace(/ORDER.(..).*?_(..)(..)(..).*/g, "$4$3$2$1")   item
).sort().map(s => s.slice(8));

console.log(sorted);

CodePudding user response:

You have to define a custom compare function for your sorting method call. And, that method should first compare dates, and then (if a date is the same) order prefixes according to your requirements

Here is my example

const order = new Map() // one can use plain Array   Array#indexOf later on
  .set('ORDERHEADER', 0)
  .set('ORDERDETAIL', 1)
  .set('ORDERITEM', 2)

const compareFn = (a, b) => {
  const [a1, a2] = a.split('_')
  const [b1, b2] = b.split('_')

  const r2 = a2.localeCompare(b2)

  if (r2 !== 0) return r2

  return order.get(a1) - order.get(b1) // or Array#indexOf as mentioned above
}

// usage
array.sort(compareFn)
  • Related