2

Perhaps am asking this question in the wrong way, but can't figure it out from the internet.

I have an array of employees that can be sorted on a variety of values (ex. position, department).

There are many employees with the same values (for example, many bartenders or many people working in guest services).

Therefore, I need those subgroups (all bartenders or all people in guest services or whatever) to then be sorted alphabetically by last name (and, ideally, then those within the group with the same last name, further sorted by first name).

This is what my sort currently looks like:

  const sorted = state.employees.sort(function(a, b) {
    if (a[filterValue] === b[filterValue]) {
      let alphaA = a.lastName, alphaB = b.lastName;
      return alphaA < alphaB ? -1 : alphaA > alphaB ? 1 : 0;
    }
    return a[filterValue] > b[filterValue] ? 1 : -1;
  });

However, the returned array gets mixed up and returns a different order on each click like so:

enter image description here

And there is no asc/desc logic implemented, so multiple clicks should, theoretically, return the same sorted array instead of one in a different order.

Presumably this is because the alphabetical comparison isn't comparing the entire group of matching values (all in accommodations department), only immediate values, but I'm not sure that's the problem and am entirely unsure how to resolve.

Help is appreciated for completing task, but explanation is very much appreciated, as I clearly don't entirely understand how sorting works.

Many thanks!

11
  • You may need to clarify your filterValue. Are you 1) sorting by category alphabetically, and then 2) sorting by first and last name? Commented Feb 23, 2017 at 20:56
  • 4
    You need to post the code that calls the sort function, see How to create a minimal, complete and verifiable example. Posting an animated GIF is a bit pointless and annoying. Commented Feb 23, 2017 at 21:03
  • 1
    Hi, @SeanKwon! Yes, so filterValue is something like 'Department' or 'Position,' which should be alphabetically sortable (Bartender, then chef, then concierge). And then within that sort (so, like, all bartenders, for example), those items should be sorted alphabetically by last name. Commented Feb 23, 2017 at 21:08
  • When I put this code into a demo, it works just fine. repl.it/FvpL/0 Commented Feb 23, 2017 at 21:11
  • 1
    Please be-nice, you are not the only one reading this.. consider to edit your comment. Commented Feb 23, 2017 at 21:22

2 Answers 2

4
var filterValue = 'department' // using a dummy one for now


state.employees.sort(function(a, b){
    if (a[filterValue] > b[filterValue]) return 1;
    if (a[filterValue] < b[filterValue]) return -1;
    //check your filters
    if (a.lastname < b.lastname ) return -1;
    if (a.lastname > b.lastname ) return 1;
    //then check their last names
    if (a.firstname < b.firstname ) return -1;
    if (a.firstname > b.firstname ) return 1;
    //then check their first names
    return 0;
});

Here's my demo: https://jsfiddle.net/zjhs20vz/

This is assuming I'm answering your question correctly. It kind of makes sense to sort based on this logic funnel from sorting filters, then if those equal, and then to last name, and then to first name

Sign up to request clarification or add additional context in comments.

7 Comments

Yes yes, this works amazing! Thank you so very much!
Aside from adding the firstname checks, how does this differ functionally from what is posted in the OP?
@EvanTrimboli honest answer, it's pretty much a rewrite. At least, imo it's easier to follow, despite the function having bad formatting via the if statements. you're right because all her function was missing was the first name check.
Right, if you swap in comparator function from the OP it produces the same results (besides first name). Nothing wrong with what you posted, but I don't see how it answers the question.
I'm no idea -- added .slice() from comments above as well, but that doesn't have an impact (same result as without). Nothing else changed, but this way is working and the other way (even with firstName) causes random re-ordering.
|
2

Instead of crafting your own comparator function, you could consider using a pre-existing library like thenBy. It allows you to sort by multiple properties using a notation like:

state.employees.sort(firstBy('position').thenBy('lastName').thenBy('firstName'));

You'll obviously have to play with it a bit for your needs and reset the sorts accordingly but it should save you from having to implement your own version

2 Comments

Thank you, @Pabs123! Ended up going with above answer, as thenBy says it can be a bit weighty and I'm dealing with a large data set, but still super useful to know about!
no problem! I just wanted to offer an alternative route, hopefully it helps someone in the future :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.