Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

137
Views
How can I "multi sort" an array of objects in Javascript by keys

I'm trying to "enhance" my sorting function for accepting multiple criteria and so doing multi sorting of my array of objects.

Sorry if this is a simple question, or if I committed "newbie" mistakes, but I'm a Frontend developer learning JS foundamentals, and I'm trying to learn how sorting functions working.

Here's my code:

const arrayOfObjects = [
    {
        name: 'John',
        age: 30,
        city: 'New York',
        details: {
            occupation: 'developer',
        }
    },
    {
        name: 'Jane',
        age: 25,
        city: 'Paris',
        details : {
            occupation: 'designer',
        }
    }
];

// This is my main sorting function that I'd like to use for "multi sorting" an array of objects
function sortByKey(criteria) {
            
    return (a, b) => {
        let comparison = 0;

        criteria.forEach(criterion => {
            const varA = (typeof resolvePath(criterion.key, a) === 'string')
            ? resolvePath(criterion.key, a).toUpperCase() : resolvePath(criterion.key, a);
            const varB = (typeof resolvePath(criterion.key, b) === 'string')
            ? resolvePath(criterion.key, b).toUpperCase() : resolvePath(criterion.key, b);

            if (varA > varB) {
                comparison = 1;
            } else if (varA < varB) {
                comparison = -1;
            }

            if(criterion.order === 'desc') {
                comparison = (comparison * -1)
            } 
        });
        
        return comparison;
    };
}

// This function is used to resolve the path of a key in an object
function resolvePath(path, obj) {
    return path.split('.').reduce(function(prev, curr) {
        return prev ? prev[curr] : null
    }, obj || self)
}

The usage of this is:

// MAIN USAGE
console.log( arrayOfObjects.sort(sortByKey([ { key: 'age' } ])) )
console.log( arrayOfObjects.sort(sortByKey([ { key: 'details.occupation', order: 'desc' } ])) )

But I would like to use it some kind of:

console.log( arrayOfObjects.sort(sortByKey([ { key: 'details.occupation' }, { key: 'age', order: 'desc' ])) )

This is because I want to give users the possibility to multi-sort my array in some kind of order, like "Age first, name second, etc..."

Thanks for any useful help, have a nice day!

about 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Create a function which returns the comparator value for each criteria. Loop through the array and call the compare function UNTIL a non-zero value is found. find will stop looking when compareByKey returns 1 or -1.

const sortByKey = (criteria) => (a, b) => {
  let returnValue = 0;
  criteria.find(c => returnValue = compareByKey(c, a, b));
  return returnValue;
}

function compareByKey({ key, order = 'asc' }, a, b) {
  const varA = resolvePath(key, a)
  const varB = resolvePath(key, b)

  let comparison = 0;

  if (varA > varB) {
    comparison = 1;
  } else if (varA < varB) {
    comparison = -1;
  }

  if (order === 'desc') {
    comparison *= -1
  }
  
  return comparison
}

If the find part is confusing or ugly:

Another way would be to reduce the comparator value of each property. But, this doesn't short circuit when a non-zero value is found.

const sortByKey = criteria => 
                    (a, b) => 
                      criteria.reduce((acc,c) => acc || compareByKey(c, a, b), 0)

or

const sortByKey = (criteria) => (a, b) => {
  let comparedValue = 0;

  for (const c of criteria) {
    comparedValue = compareByKey(c, a, b);

    if (comparedValue)
      return comparedValue;
  }
  
  return comparedValue;
}

const arrayOfObjects = [{
    name: 'John',
    age: 30,
    city: 'New York',
    details: {
      occupation: 'developer',
    }
  },
  {
    name: 'Jane',
    age: 25,
    city: 'Paris',
    details: {
      occupation: 'designer',
    }
  },
  // added another designer for testing
  {
    name: 'Jane 2',
    age: 30,
    city: 'Paris',
    details: {
      occupation: 'designer',
    }
  }
];

const sortByKey = (criteria) => (a, b) => {
  let returnValue = 0;
  criteria.find(c => returnValue = compareByKey(c, a, b));
  return returnValue;
}

function compareByKey({ key, order = 'asc' }, a, b) {
  const varA = resolvePath(key, a)
  const varB = resolvePath(key, b)

  let comparison = 0;

  if (varA > varB) {
    comparison = 1;
  } else if (varA < varB) {
    comparison = -1;
  }

  if (order === 'desc') {
    comparison *= -1
  }
  
  return comparison
}

// This function is used to resolve the path of a key in an object
function resolvePath(path, obj) {
  return path.split('.').reduce(function(prev, curr) {
    return prev ? prev[curr] : null
  }, obj || self)
}

console.log(arrayOfObjects.sort(sortByKey([
  { key: 'details.occupation' }, 
  { key: 'age', order: 'desc' }
])))

about 4 years ago · Santiago Trujillo Report

0

You can try :

const arrayOfObjects = [{
        id: 3,
        name: 'Jane',
        age: 25,
        city: 'Paris',
        details: {
            occupation: 'designer',
        }
    },
    {
        id: 1,
        name: 'John',
        age: 30,
        city: 'New York',
        details: {
            occupation: 'developer',
        }
    },
    {
        id: 2,
        name: 'Bob',
        age: 25,
        city: 'New York',
        details: {
            occupation: 'developer',
        }
    },
];

let sortByKey = function (a, b, keys) {
    for (let key of keys) {
        if (a[key.key] != b[key.key]) return (a[key.key] > b[key.key] ? 1 : -1) * (key.order == 'desc' ? -1 : 1);
    }
    return 0;
}


let result = arrayOfObjects.sort((a, b) => sortByKey(a, b, [{ key: 'age' }, { key: 'city', order: 'desc' }]));
console.log(result);
about 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!