我想根据预定义的正则表达式顺序对服装尺寸数组进行排序。
表达式数组如下:
const sizeOrder = [
/One Size/,
/[X/S]+S/i,
/^S$/i,
/^M$/i,
/^L$/i,
/[X]+L/i,
/[4-9]XL/i,
/[0-9,]+/,
];
一种对数组进行排序的整洁高效的方法,例如,如下所示:
const sizes = [
'45,5',
'S',
'XXS',
'XXL',
'XS',
'4XL',
'One Size',
'0',
'32',
'42,5',
'18',
'XXS/XS',
'XXXS',
'L'
];
第一步,我将为相应的正则表达式创建存储桶,如果存在匹配项,则将该值推入存储桶,如下所示:
function exampleSort() {
const bucket = Array.from(new Array(sizeOrder.length), () => []);
sizes.forEach(size => {
const i = sizeOrder.findIndex(order => order.test(size));
if (i > -1) {
bucket[i].push(size);
}
});
}
在那之后,我将遍历每个存储桶并对它们进行相应的排序,然后将这些数组连接在一起。
但是我有两个问题:
XXS/XS
的特殊情况如何?我将如何对该存储桶进行排序,以使XXS/XS
位于XXS
和XS
之间?
这似乎是当务之急和幼稚的实现。还有其他方法可以更有效地做到这一点吗?
这是我的预期输出:
const sorted = [
'One Size',
'XXXS',
'XXS',
'XXS/XS',
'XS',
'S',
'L',
'XXL',
'4XL',
'0',
'18',
'32',
'42,5',
'45,5'
];
答案 0 :(得分:2)
一种选择是遍历字符串,推送到由匹配的正则表达式索引的Map
数组。然后,对每个数组进行排序,并展平以获得结果。
请注意增加了^
和$
锚点,以确保只有完全匹配才能满足.test
。
const sizeOrder = [
/^One Size$/,
/^[X/S]+S$/i,
/^S$/i,
/^M$/i,
/^L$/i,
/^[X]+L$/i,
/^[4-9]XL$/i,
/^[0-9,]+$/,
];
const patternMap = new Map(sizeOrder.map(pattern => [pattern, []]));
const sizes = [
'45,5',
'S',
'XXS',
'XXL',
'XS',
'4XL',
'One Size',
'0',
'32',
'42,5',
'18',
'XXS/XS',
'XXXS',
'L'
];
sizes.forEach((str) => {
const matchingPattern = sizeOrder.find(pattern => pattern.test(str));
patternMap.get(matchingPattern).push(str);
});
const valuesArr = [...patternMap.values()];
valuesArr.forEach(arr => arr.sort((a, b) => b.localeCompare(a)));
// sort the last one from /^[0-9,]+$/ differently:
valuesArr[valuesArr.length - 1].sort();
console.log(valuesArr.flat());
或者,使用模式数组和可选的关联排序功能,您可以执行以下操作:
const sizeOrder = [
{ pattern: /^One Size$/ },
{ pattern: /^[X/S]+S$/i, }, // insert your custom sort logic for XXS/XS here
{ pattern: /^S$/i },
{ pattern: /^M$/i },
{ pattern: /^L$/i },
{ pattern: /^[X]+L$/i },
{ pattern: /^[4-9]XL$/i },
{ pattern: /^[0-9,]+$/, sort: arr => arr.sort() }
];
const patternMap = new Map(sizeOrder.map(({ pattern }) => [pattern, []]));
const sizes = [
'45,5',
'S',
'XXS',
'XXL',
'XS',
'4XL',
'One Size',
'0',
'32',
'42,5',
'18',
'XXS/XS',
'XXXS',
'L'
];
sizes.forEach((str) => {
const { pattern } = sizeOrder.find(({ pattern }) => pattern.test(str));
patternMap.get(pattern).push(str);
});
const valuesArr = [...patternMap.values()];
valuesArr.forEach((arr, i) => {
const sort = sizeOrder[i].sort;
if (sort) {
sort(arr);
} else {
arr.sort((a, b) => b.localeCompare(a));
}
});
console.log(valuesArr.flat());
答案 1 :(得分:1)
您可以通过检查
使用分段方法如果字符串包含斜杠,则将其拆分并取平均值,
如果字符串中包含其他一些模式,则返回一个值,以反映顺序,或者将'S'
,'M'
'L'
,
如果字符串包含一些前导'X'
或数字后跟'S'
或'L'
,则获取数字或以'X'
开头的计数并使用将值向正确方向移动的一个因素。
const
getOrder = s => {
var standard = { s: -0.5, m: 0, l: 0.5 },
x = 0;
if (s.includes('/')) return s.split('/').map(getOrder).reduce((a, b) => a + b) / 2;
if (/^One Size$/.test(s)) return 1;
if (/^[lms]$/i.test(s)) return standard[s.toLowerCase()] + 2;
if (/x+[sl]$/i.test(s)) {
if (/^\dx/i.test(s)) {
x = s[0];
} else {
while (s[x].toLowerCase() === 'x') x++;
}
return standard[s.slice(-1).toLowerCase()] * (1 + 0.01 * x) + 2;
}
if (/^[0-9,]+$/.test(s)) return 3;
return 0;
},
sizes = ['45,5', 'S', 'XXS', 'XXL', 'XS', '4XL', 'One Size', '0', '32', '42,5', '18', 'XXS/XS', 'XXXS', 'L', 'M'];
sizes.sort((a, b) => getOrder(a) - getOrder(b) || a.replace(',', '.') - b.replace(',', '.'));
console.log(sizes);
.as-console-wrapper { max-height: 100% !important; top: 0; }