Human Sort
Sorts elements in a way that follows english conventions
by sperske
HTML
<table id='List'>
<tr>
<td>Now That's What I Call Music 1</td>
</tr>
<tr>
<td>now That's What I Call Music 11</td>
</tr>
<tr>
<td>August And Everything After</td>
</tr>
<tr>
<td>Now That's What I Call Music 5</td>
</tr>
<tr>
<td>The 1975</td>
</tr>
<tr>
<td>They're 10,000 Strong</td>
</tr>
</table>
JavaScript
const list = document.getElementById('List');
let items = Array.from(list.getElementsByTagName('td')).map(e => e.innerText);
console.log(items);
function normalize(item) {
let name = item.toUpperCase().replace('THE ', '');
let trailingNumberData = /.*\D(\d+)$/.exec(name);
let trailingNumber;
if (trailingNumberData) {
name = name.substring(0, name.length-trailingNumberData[1].length);
trailingNumber = parseInt(trailingNumberData[1], 10);
}
return { name, trailingNumber };
}
function humanSort(items) {
let sortedItems = items;
//return items sorted by skipping "The" and ordering trailing
//numbers numerically.
sortedItems.sort((a, b) => {
let A = normalize(a);
let B = normalize(b);
if (A.name === B.name) {
if (A.trailingNumber && B.trailingNumber) {
return A.trailingNumber - B.trailingNumber;
} else if(!A.trailingNumber && B.trailingNumber) {
return -1;
} else if(A.trailingNumber && !B.trailingNumber) {
return 1;
} else {
return 0;
}
} else {
return A.name.localeCompare(B.name);
}
});
return sortedItems;
}
console.log(humanSort(items));
//render results
list.innerHTML = '';
humanSort(items).forEach((v, i) => {
let row = document.createElement('tr');
row.innerHTML = `<th>${i + 1}</th><td>${v}<td>`;
list.append(row);
});