Home > Mobile >  sorting javascript array on custom string condition
sorting javascript array on custom string condition

Time:11-22

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);

  • Related