Hello I'm facing a problem.
I want to order my table by decimal and after by letter.
For exemple I got this :
5.3 Choice 3
A-Choice 4
1.2 Choice 1
1.5 Choice 2
C-Choice 5
And I want it to be that way :
1.2 Choice 1
1.5 Choice 2
5.3 Choice 3
A-Choice 4
C-Choice 5
I tried something like that
const compare = (a, b) => {
if (!isNaN(b.label.charAt(0)))
{
if (a.label === b.label) {
return 0
};
const aArr = a.label.split("."), bArr = b.label.split(".");
for (let i = 0; i < Math.min(aArr.length, bArr.length); i++) {
if (parseInt(aArr[i]) < parseInt(bArr[i])) {
return -1
};
if (parseInt(aArr[i]) > parseInt(bArr[i])) {
return 1
};
}
if (aArr.length < bArr.length) {
return -1
};
if (aArr.length > bArr.length) {
return 1
};
return 0;
}
else
{
return a.label > b.label;
}
};
processus.sort(compare);
But it's not working.. Thanks.
Try the sort using string comparison (i.c. localeCompare).
localeCompare is not sufficient if the values after 'Choice' may be > 9 (e.g. '1.2 Choice 23'. In that case you'll need to to sort twice, something like the snippet.
const toSort = getToSort();
log(`\n**Choice always [< 10], localeCompare sufficient`,
toSort.simple
.sort((a, b) => a.localeCompare(b))
.join(`\n`)
);
// this does not work for a choice values > 9
log(`\n**Choice may be [> 9], localeCompare insufficient`,
toSort.complex
.sort((a, b) => a.localeCompare(b))
.join(`\n`)
);
// so, [Choice > 9] needs more work
// The plan:
// 1. Sort on string start (e.g. '1.2', 'C'), create
// an Object from that with key = string start,
// values = [next values] and convert it to an
// Array of entries;
// 2. Sort numeric within the entries Array on the
// last value ('Choice [value]'), which is already
// converted to number. Remap the result to sorted
// strings.
const linesSorted = Object.entries(toSort.complex /*1*/
.map(v => v.split(/[\s-]/))
.sort(([a, , ], [b, , ]) => a.localeCompare(b))
.reduce( (acc, [v1, v2, v3]) =>
({ ...acc, [v1]: [...(acc[v1] || []), [v2, +v3]]}), {} ) )
.reduce( (acc, [key, value]) => /*2*/
[...acc, [key,
value.sort(([, a], [, b]) => a - b, [] ).map(v =>
`${key} ${v.join(` `)}`)]], [])
.map(([, value]) => value.join(`\n`))
.join(`\n`);
log(`\n**Choice may be [> 9], need more work`, linesSorted);
// helpers
function getToSort() {
// return strings to sort, already splitted to array
return {
simple: `5.3 Choice 3
A-Choice 4
1.2 Choice 1
1.5 Choice 2
C-Choice 5`.split(`\n`).map(v => v.trim()),
complex: `1.5 Choice 3
5.3 Choice 3
1.2 Choice 55
A-Choice 4
1.2 Choice 1
1.5 Choice 11
C-Choice 5
A-Choice 110
1.2 Choice 2`.split(`\n`).map(v => v.trim())
};
}
function log(...strs) {
const pre = document.querySelector(`pre`);
strs.forEach(str => pre.textContent += `${str}\n`);
}
<pre></pre>
This can easily be achieved with localeCompare.
const arr = [
'5.3 Choice 3',
'A-Choice 4',
'1.2 Choice 1',
'1.5 Choice 2',
'C-Choice 5',
];
const result = arr.sort((a, b) => a.localeCompare(b));
console.log(result);