I have an array in the following format.
const arr = [{name:'11'},{name:'10'},{name:'9'},{name:'8'},{name:'7'}
{name:'6'},{name:'5'},{name:'4'},{name:'3'},{name:'2'},{name:'1'}
{name:'UN'},{name:'PG'},{name:'LN'},
{name:'12'},{name:'13'}]
I can sort it to get an output like below.
arr.sort((x, y)=> {
if(x.name == 'LN' || x.name=='UN' || x.name== 'PG' || (parseInt(x.name)<parseInt(y.name))) {
return -1;
}
return 0;
})
Current Output : simplified for easy visualization
[LN,PG,UN,1,2,3,4,5,6,7,8,9,10,11,12,13]
I want PG to come after UN. Should do a swap like below after sorting or can it be done in the sort function it self?
[arr[1], arr[2]] = [arr[2],arr[1]]
Expected Output : simplified for easy visualization
[LN,UN,PG,1,2,3,4,5,6,7,8,9,10,11,12,13]
CodePudding user response:
One way is to give the name
a rank,
Assuming your numbers are always positive, a really simple way to rank is use a lookup for the text, making them less than 0. If new name types appear in the future it's just a case of updating the rank lookup. You can then sort on this rank function.
eg..
const arr = [{name:'11'},{name:'10'},{name:'9'},{name:'8'},{name:'7'},
{name:'6'},{name:'5'},{name:'4'},{name:'3'},{name:'2'},{name:'1'},
{name:'UN'},{name:'PG'},{name:'LN'},
{name:'12'},{name:'13'}];
const ranks = {
LN: -3,
UN: -2,
PG: -1
}
function rank(n) {
if (ranks[n]) return ranks[n]
else return Number(n);
}
arr.sort((a,b) => {
return rank(a.name) - rank(b.name);
});
console.log(arr);
CodePudding user response:
Create a value map for the strings:
const arr = [{name:'11'}, {name:'10'}, {name:'9'}, {name:'8'}, {name:'7'}, {name:'6'}, {name:'5'}, {name:'4'}, {name:'3'}, {name:'2'}, {name:'1'}, {name:'UN'}, {name:'PG'}, {name:'LN'}, {name:'12'}, {name:'13'}];
const result = arr.sort((oA, oB) => {
// Handle case of same value:
if (oA.name === oB.name) return 0;
// Coerce to numbers:
const nA = Number(oA.name);
const nB = Number(oB.name);
// Handle the case for two numbers:
if (Number.isInteger(nA) && Number.isInteger(nB)) return nA - nB;
// Handle the case for two non-numbers:
if (Number.isNaN(nA) && Number.isNaN(nB)) {
const valueMap = { LN: 0, UN: 1, PG: 2 };
return valueMap[oA.name] - valueMap[oB.name];
}
// Handle the case for one number and one non-number:
return Number.isNaN(nA) ? -1 : 1;
});
console.log(result);