Inv*_*nge 7 html javascript sorting null
我正在使用下面的 JavaScript 代码按字母顺序和数字对表格进行排序。但是,它将带有null
值的行放在顶部而不是底部。
在下面的图片中,取自我正在处理的这个URL,当在 Rank Change 列中从最大到最小对表进行排序时,空值位于顶部而不是底部。
*在此表中,Null
值是带有 NEW 标签或破折号的单元格。*问题适用于所有列/行
不应该将 Null 归类为小于 1 并按此类排序吗?我究竟做错了什么?
任何帮助都非常感谢。
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) );
})));
Run Code Online (Sandbox Code Playgroud)
您可以先检查null
值,然后检查两个值的有限性,例如可强制转换为数字的数字或字符串,然后取数字的增量或按字符串排序。
例子:
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
Run Code Online (Sandbox Code Playgroud)
代码:
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));
Run Code Online (Sandbox Code Playgroud)
工作示例:
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
Run Code Online (Sandbox Code Playgroud)
将 null 视为 -Infinity 应该修复排序。我可以建议在 th 元素上使用 asc 属性,这样您就可以避免使用“this”。
// don't know if theres any other listeners on the th element so i clear them before use my code ( just for testing )
document.querySelectorAll('th').forEach((th, idx) => th.removeEventListener('click', () => {}, true));
document.querySelectorAll('th').forEach((th, idx) => th.addEventListener('click', (() => {
const table = th.closest('table');
th.asc = !th.asc;
[...table.querySelectorAll('tr:nth-child(n+2)')]
.sort((a, b) => +((th.asc ? a : b).children[idx].innerText || -Infinity) - +((th.asc ? b : a).children[idx].innerText || -Infinity))
.forEach(tr => table.appendChild(tr));
})));
Run Code Online (Sandbox Code Playgroud)
如果它是 NaN,您应该将更改设置为 0 或 +-Infinity,具体取决于您希望其顶部底部或 0 更改。(仅在比较时应用值变化)
为了便于理解,我对代码进行了扩展。
检查此 ComparerNew 并根据您的需要进行修改。
const comparerNew = (idx, asc) => (a, b) => ((v1, v2) => {
if (isNaN(v1)) {
v1=0; // or Infinity
}
if (isNaN(v2)) {
v2=0; // or Infinity
}
return v1 !=='' && 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(comparerNew(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
.forEach(tr => table.appendChild(tr) );
console.log("sorded");
})));
Run Code Online (Sandbox Code Playgroud)