Babulaas
Babulaas

Reputation: 865

Sort observable array - if an object has a specific property set this object first

In my function, I have this code to retrieve a list of objects:

this.personService.getAccountOverview().subscribe(persons => this.personsSubject.next(persons));

The output will be something like this:

[
  { name: 'John Doe', age: 44, isCrazy: false, isAnotherLevelCrazy: false, isExtremeCrazy: false },
  { name: 'Jane Doe', age: 28, isCrazy: false, isAnotherLevelCrazy: false, isExtremeCrazy: false },
  { name: 'Crazy Doe', age: 36, isCrazy: true, isAnotherLevelCrazy: false, isExtremeCrazy: false },
  { name: 'Extreme Doe', age: 23, isCrazy: false, isAnotherLevelCrazy: true, isExtremeCrazy: true }
]

What I try to achieve is if any of 3 crazy properties is set to true put this object on top of the list. There can be more objects where this is true than place those sorted by name on top of the list.

below the crazy people will be the "non" crazy people also sorted by name. It should be ordered like this:

crazy doe, extreme doe, jane doe and then john doe.

I tried this but I do not get the right results / no sorting (also I did not start on the name sorting for the top items yet):

this.personService.getAccountOverview().subscribe(persons => {
  persons.sort((a,b) => {
    if(b.isCrazy || b.isAnotherLevelCrazy || extremeCrazy) {
      return 1;
    }
  }); 
  this.personsSubject.next(persons)
});

It look a lot but the main question is How can you sort the list based on one property and use a "then" or something else to sort the list again. Sort the list with a primary value and a secondary value

Can anyone help me with this?

My solution:

const isCrazyHuman = c => c.isCrazy || c.isAnotherLevelCrazy || c.isExtremeCrazy;

const result = persons.sort((a, b) => {
  const aCrazy = isCrazyHuman(a);
  const bCrazy = isCrazyHuman(b);
  if(!aCrazy && !bCrazy || aCrazy && bCrazy) {
    return a.name.localeCompare(b.name);
  } else if (aCrazy) {
      return -1
  } else {
      return 1;
  }
});

Thank you Mureinik. I could't answer this question because of the closed status. So I updated the question

Upvotes: -2

Views: 43

Answers (1)

Mureinik
Mureinik

Reputation: 312076

Your implementation checks only the properties of b, which is incorrect - if a were also crazy, b would not necessarily be "greater" than a.

The correct logic, as you described it, should be as follows:

  • If a is crazy but b is not, a should come first
  • If b is crazy but a is not, b should come first
  • If a and b are equally crazy, sort them by their names.

Translated to code, it would look like this:

const isCarzy = p => p.isCrazy || p.isAnotherLevelCrazy || p.isExtremeCrazy;
persons.sort((a, b) => {
    const aCrazy = isCarzy(a);
    const bCrazy = isCarzy(b);
    if (aCrazy) {
        if (!bCrazy) {
            return -1;
        }
    } else {
        if (bCrazy) {
            return 1;
        }
    }
    return a.name.localeCompare(b.name);
});

Upvotes: 1

Related Questions