0

I have an array of objects and I'd like to dynamically sort the list based on a parameter. Here is an example that show's what works and what doensn't work when I try to use parameter.

const field = 'email'
const users = [{Array of users}]
users = users.sort((a, b) => (a.email > b.email? 1 : -1)); << WORKS
users = users.sort((a, b) => (a.['email'] > b['email']? 1 : -1));  << WORKS

users = users.sort((a, b) => (a.[`'${field}'`] > b[`'${field}'`]? 1 : -1));  << DOESN'T WORK

How can I dynamically sort the list based on a defined parameter?

2
  • Just a[field] or b[field] given it’s a string Commented Sep 2, 2020 at 17:20
  • 1
    Side note; assuming that an email variable is a string, you should be using a.email.localeCompare(b.email) Commented Sep 2, 2020 at 17:22

2 Answers 2

2

You can actually pass variables directly into the square bracket notation:

users = users.sort((a, b) => a[field] > b[field] ? 1 : -1);

I don't recommend this, but if you did want to use template strings it would look more like this:

a[`${field}`]

If you are sorting by string fields, you'd be better off using localeCompare for your comparison:

users = users.sort((a, b) => { 
  return a[field].toLowerCase().localeCompare(b[field].toLowerCase());
});

I also wanted to point out that for a numeric sort, it's more common to subtract the numbers than to compare them (this is descending order, switch the order to a[field] - b[field] for ascending):

users = users.sort((a, b) => b[field] - a[field]);

A few additional helper functions based on the discussion in the comments:

function stringSort(a, b) {
  return a[field].toLowerCase().localeCompare(b[field].toLowerCase());
}

function numberSort(a, b) {
  return b[field] - a[field];
}

users = users.sort(field === 'email' ? stringSort : numberSort);
Sign up to request clarification or add additional context in comments.

6 Comments

This works, thx! Now, the last step is i want to lowercase the string so it sorts on lowercase values. I tried this users = users.sort((a, b) => a[field].toLowerCase() > b[field].toLowerCase() ? 1 : -1); but it doesn't like it. How to?
Added another example using localeCompare, which is the preferred method for sorting strings.
I get error of a[field].toLowerCase is not a function . FYI, i am setting field this way when using real exampe. const field = payload.sortfield where payload is object and sortfield is just a string of say "email". Not sure if that makes a difference on why this isn't working.
Yes, localeCompare will only work if your fields are strings. You may need to add some logic to use the a[field] > b[field] ? 1 : -1 numeric fields, and use localeCompare for string fields.
I added a basic example of how you can accomplish this. Note that field has to be defined in the same scope as your field variable, otherwise field inside the sort function will be undefined.
|
0

this ' is extra in last statement,

users = users.sort((a, b) => (a.[`${field}`] > b[`${field}`]? 1 : -1));  

btw the result of above is the same this one (for demonstration purpose only

users = users.sort((a, b) => a[field.toString()] > b[field.toString()] ? 1 : -1);

so the best way is the one that @wex has already suggested which is to directly put the variable in brackets:

users = users.sort((a, b) => a[field] > b[field] ? 1 : -1);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.