Home > Mobile >  Order object keys by two conditions but give priority to the first one
Order object keys by two conditions but give priority to the first one

Time:05-31

I am trying to sort the keys of an object accoring to two conditons, first by having the word Current and then by Conv but I dont wont the last condition to undo the previous one.

const obj = {
  'Additional Traffic': 2,
  'Current Conv': 1,
  'Additional Conv': 0.5,
  'Current Rev': 100,
  'Additional Rev': 50
}

const res = Object.keys(obj).sort((a, b) => a.includes('Current') &&  a.includes('Conv') ? -1 : 0)

// Expected output
// Current Conv  
// Current Rev 
// Additional Traffic  
// Additional Conv 
// Additional Rev  

console.log(res)

CodePudding user response:

Given that second word is not sorted alphabetically i suggest to create a sortHash to give numerical value to words..

  • This can be improved by using only the initial letter and adding more rules..

  • also i am trusting that is only 2 words.. can be improved to handle more words in the logic

    const [wordA1, wordA2, wordA3, wordA4 /*...*/] = a.split(' ')

Code

const obj = {'Additional Traffic': 2,'Current Conv': 1,'Additional Conv': 0.5,'Current Rev': 100,'Additional Rev': 50,}

const sortHash = {
  word1: {
    Current: 0,
    Additional: 1,
  },
  word2: {
    Traffic: 0,
    Conv: 1,
    Rev: 2,
  },
}

const res = Object.keys(obj).sort((a, b) => {
  const [wordA1, wordA2] = a.split(' ')
  const [wordB1, wordB2] = b.split(' ')
  return (
    sortHash.word1[wordA1] - sortHash.word1[wordB1] ||
    sortHash.word2[wordA2] - sortHash.word2[wordB2]
  )
})

console.log(res)

CodePudding user response:

usually you would have a function which compare using first criteria and if result is 0 (equality) you compare with next criteria.

So for you that would be:

const obj = {
  'Additional Traffic': 2,
  'Current Conv': 1,
  'Additional Conv': 0.5,
  'Current Rev': 100,
  'Additional Rev': 50
}

const res = Object.keys(obj).sort((a, b) => {
  let result = b.indexOf('Current') - a.indexOf('Current');
  if (result === 0) {
    result = b.indexOf('Conv') - a.indexOf('Conv');
  }
  return result;
});

// Expected output
// Current Conv  
// Current Rev 
// Additional Traffic  <-- need one more rule for this one to be sorted properly
// Additional Conv 
// Additional Rev  

console.log(res)

Note that if you have a lot of words to check you can use an array like so:

const obj = {
  'Additional Traffic': 2,
  'Current Conv': 1,
  'Additional Conv': 0.5,
  'Current Rev': 100,
  'Additional Rev': 50
}

const SORT_ARRAY = ['Current', 'Traffic', 'Conv'];

const res = Object.keys(obj).sort((a, b) => {
  let sortCriteriaIdx = 0;
  let result = 0;
  while (result === 0 && sortCriteriaIdx < SORT_ARRAY.length) {
    const criteria = SORT_ARRAY[sortCriteriaIdx];
    result = b.indexOf(criteria) - a.indexOf(criteria);
    sortCriteriaIdx  ;
  }
  return result;
});

// Expected output
// Current Conv  
// Current Rev 
// Additional Traffic
// Additional Conv 
// Additional Rev  

console.log(res)

CodePudding user response:

const obj = {
  'Additional Traffic': 2,
  'Current Conv': 1,
  'Additional Conv': 0.5,
  'Current Rev': 100,
  'Additional Rev': 50
}

    const data = Object.keys(obj).sort((key1, key2) => {
        const key1ContainsCurrent = key1.includes('Current');
        const key2ContainsCurrent = key2.includes('Current');
        const key1ContainsConv = key1.includes('Conv');
        const key2ContainsConv= key2.includes('Conv');
        debugger;
        if (key1ContainsCurrent || ((!key1ContainsCurrent && !key2ContainsCurrent) && key1ContainsConv)) {
            return -1
        }
        if (key2ContainsCurrent || key2ContainsConv) {
           return 1
        }
        return 0;

    });
    
console.log(data);

  • Related