Sort/order 由两个条件(名称序列和日期)组成的字符串数组- JavaScript

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

尝试 sort/order 这个字符串数组时遇到一些问题。响应中返回的文件名有数千个,下面以 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'
];

一个简单的 array.sort() 解决了一半的问题,因为它将按字母顺序排列字符串并固有地对日期进行排序。

我需要的是排序的“顺序”顺​​序以及日期顺序。所以 prioSequence = ['ORDERHEADER', 'ORDERDETAIL', 'ORDERITEM']; 将是我想要看到的序列。

预期输出为:

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'
];

任何 help/guidance 将不胜感激!谢谢!

在字符串前加上确定排序的部分,即 yymmdd 和“ORDER”字符串中的 2 个字母,事实证明,当您选择这些单词的第 7 和第 8 个字母时(EA、ET、TE ), 它们将被正确排序。然后在对项目进行排序后,再次删除该前缀。

结果如下:

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, "") + item
).sort().map(s => s.slice(8));

console.log(sorted);

扩展它

如果您有更多 prefix-words 个要控制顺序,请按预期顺序创建一个数组。该解决方案然后将该数组转换为查找映射(为给定单词提供 4 个字符的序列号)。对 replace 的调用需要一个回调参数,它将进行查找并为该序列添加前缀。这是相关代码:

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 priorities = [
    'ORDERHEADER',
    'ORDERDETAIL',
    'ORDERITEM',
];

// Map the priority array to an object for faster look-up
let priMap = Object.fromEntries(priorities.map((word, i) => 
    [word, ("000" + i).slice(-4)]
));

let sorted = array.map(item => 
    item.replace(/(.*?)_(..)(..)(..).*/g, (all, word, dd, mm, yy) =>
        yy + mm + dd + (priMap[word] ?? "----") + all
    )
).sort().map(s => s.slice(10));

console.log(sorted);

您必须为排序方法调用定义自定义比较函数。而且,该方法应该首先比较日期,然后(如果日期相同)根据您的要求订购前缀

这是我的例子

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) // TODO: re-write to date comparison a2 vs b2

  if (r2 !== 0) return r2

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

// usage
array.sort(compareFn)