I'm using the below JavaScript code to sort my tables alphabetically and numerical. However, it puts rows with null
values at the top instead of the bottom.
In the below image, taken from this URL I am working on, when sorting the table from biggest to smallest in the Rank Change column, nulls are at the top instead of the bottom.
*In this table, Null
values are the cells with the NEW tag or a dash.
*The problem applies to all columns/rows
Shouldn't Nulls be classed as less than 1 and sorted as such? What am I doing wrong?
Any help is really appreciated.
const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent;
const comparer = (idx, asc) => (a, b) => ((v1, v2) =>
v1 !=='' && v2 !=='' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2)
)(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
document.querySelectorAll('th').forEach(th => th.addEventListener('click', (() => {
const table = th.closest('table');
Array.from(table.querySelectorAll('tr:nth-child(n+2)'))
.sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
.forEach(tr => table.appendChild(tr) );
})));
You could take a check for null
values first and the check both values for finiteness, like numbers or strings who are coercible to number and then take either the delta of the numbers or sort by string.
Examples:
v1 v2 (v1 === null) - (v2 === null) isFinite(v1) && isFinite(v2) result
---- ---- ----------------------------- ---------------------------------------- ------
null null true - true -> 0 true -> v1 - v2 0
null abc true - false -> 1 1
null 2 true - false -> 1 1
abc null false - true -> -1 -1
2 null false - true -> -1 -1
abc abc false - false -> 0 false -> v1.toString().localeCompare(v2) 0
abc 2 false - false -> 0 false -> v1.toString().localeCompare(v2) 1
2 abc false - false -> 0 false -> v1.toString().localeCompare(v2) -1
2 2 false - false -> 0 true -> v1 - v2 0
Code:
const comparer = (idx, asc) => (a, b) => ((v1, v2) =>
(v1 === null) - (v2 === null) ||
(isFinite(v1) && isFinite(v2)
? v1 - v2
: v1.toString().localeCompare(v2)
)
)(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
Working Example:
var array = [null, 2, 1, 20, 11, 'b', 'aaa', 'a', null];
array.sort((v1, v2) =>
(v1 === null) - (v2 === null) ||
(isFinite(v1) && isFinite(v2)
? v1 - v2
: v1.toString().localeCompare(v2)
)
);
console.log(...array);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With