Ricardo Sanchez
Ricardo Sanchez

Reputation: 5157

How to sort an array of objects by a predefined value?

Given the following array of objects:

const arr = [
  {
    "unit": "Room 2",
    "name": "House A"
  },
  {
    "unit": "Room 1",
    "name": "House A"
  },
  {
    "unit": "Main House",
    "name": "House A"
  },
  {
    "unit": "Room 3",
    "name": "House B"
  },
  {
    "unit": "Room 1",
    "name": "House B"
  },
  {
    "unit": "Room 2",
    "name": "House B"
  },
  {
    "unit": "Main House",
    "name": "House B"
  },
]

I would like to sort it like the below example:

[
  { unit: 'Main House', name: 'House A' },
  { unit: 'Room 1', name: 'House A' },
  { unit: 'Room 2', name: 'House A' },
  { unit: 'Main House', name: 'House B' },
  { unit: 'Room 1', name: 'House B' },
  { unit: 'Room 2', name: 'House B' },
  { unit: 'Room 3', name: 'House B' }
]

Where I can say move the objects where unit === 'Main House' to the top of the other values that share the same name

I try the below to no avail

const result = arr.sort((c1, c2) => (c1.unit === 'Main House' || c2.unit === 'Main House') ? 1 : -1)

Upvotes: 1

Views: 45

Answers (2)

VLAZ
VLAZ

Reputation: 28980

Sort by name first and by unit second with an exception for "Main House" to go to the top. String#localeCompare makes sorting comparison a lot easier:

const arr = [
  { "unit": "Room 2"    , "name": "House A" },
  { "unit": "Room 1"    , "name": "House A" },
  { "unit": "Main House", "name": "House A" },
  { "unit": "Room 3"    , "name": "House B" },
  { "unit": "Room 1"    , "name": "House B" },
  { "unit": "Room 2"    , "name": "House B" },
  { "unit": "Main House", "name": "House B" },
];

arr.sort((a, b) => {
  const nameOrder = a.name.localeCompare(b.name);
  if (nameOrder !== 0)
    return nameOrder;
  if(a.unit === "Main House")
    return -1;
  if (b.unit === "Main House")
    return 1;
  return a.unit.localeCompare(b.unit);
});

console.log(arr)

Which can be shortened with some (ab)use of logical operators and type coercion:

const arr = [{ "unit": "Room 2", "name": "House A" }, { "unit": "Room 1", "name": "House A" }, { "unit": "Main House", "name": "House A" },{ "unit": "Room 3", "name": "House B" },{ "unit": "Room 1", "name": "House B" },{ "unit": "Room 2", "name": "House B" },{ "unit": "Main House", "name": "House B" },];

arr.sort((a, b) => 
  a.name.localeCompare(b.name) ||
  ((b.unit === "Main House") - (a.unit === "Main House")) ||
  a.unit.localeCompare(b.unit)
);

console.log(arr);

Upvotes: 1

Unmitigated
Unmitigated

Reputation: 89214

You can check the criteria in order like so:

const arr=[{unit:"Room 2",name:"House A"},{unit:"Room 1",name:"House A"},{unit:"Main House",name:"House A"},{unit:"Room 3",name:"House B"},{unit:"Room 1",name:"House B"},{unit:"Room 2",name:"House B"},{unit:"Main House",name:"House B"}];
arr.sort((a, b) => a.name !== b.name ? a.name.localeCompare(b.name) : 
    a.unit === b.unit ? 0 : 
    a.unit === 'Main House' ? -1 : 
    b.unit === 'Main House' ? 1 : a.unit.localeCompare(b.unit))
console.log(arr);

Upvotes: 3

Related Questions