1

I'm trying to write a helper function in JavaScript that takes an unsorted array of objects and an array of fields and sorts the array in place based on the given fields. Here's what I have so far:

const sortByFieldsInPlace = (arr, fieldNames) => {
  arr.sort((a, b) => {
    for (const field of fieldNames) {
      if (a[field] > b[field]) return 1;
      if (a[field] < b[field]) return -1;
    }
  });
};

It seems to work so far:

const arr1 = [
  { name: 'A', code: 'D' },
  { name: 'B', code: 'A' },
  { name: 'A', code: 'Z' },
  { name: 'A', code: 'A' },
  { name: 'B', code: 'D' },
  { name: 'B', code: 'B' },
  { name: 'B', code: 'B' }
];
sortByFieldsInPlace(arr1, ['name', 'code'])
console.log(arr1)
// [
//   { name: 'A', code: 'A' },
//   { name: 'A', code: 'D' },
//   { name: 'A', code: 'Z' },
//   { name: 'B', code: 'A' },
//   { name: 'B', code: 'B' },
//   { name: 'B', code: 'B' },
//   { name: 'B', code: 'D' }
// ]

const arr2 = [
  { name: 'A', code: 'D' },
  { name: 'B', code: 'A' },
  { name: 'A', code: 'Z' },
  { name: 'A', code: 'A' },
  { name: 'B', code: 'D' },
  { name: 'B', code: 'B', status: 10 },
  { name: 'B', code: 'B', status: 9 }
];
sortByFieldsInPlace(arr2, ['name', 'code', 'status'])
console.log(arr2)
// [
//   { name: 'A', code: 'A' },
//   { name: 'A', code: 'D' },
//   { name: 'A', code: 'Z' },
//   { name: 'B', code: 'A' },
//   { name: 'B', code: 'B', status: 9 },
//   { name: 'B', code: 'B', status: 10 },
//   { name: 'B', code: 'D' }
// ]

Does this look good or does anyone have a better solution?

Johnny Metz
  • 5,977
  • 18
  • 82
  • 146
  • Does this answer your question? [Sort array of objects by string property value](https://stackoverflow.com/questions/1129216/sort-array-of-objects-by-string-property-value). Do look beyond the accepted answer - [this answer](https://stackoverflow.com/a/4760279/215552) solves the multiple-properties question. – Heretic Monkey Jan 08 '20 at 20:20
  • 1
    `String.prototype.localeCompare()` - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare – norbitrial Jan 08 '20 at 20:22
  • what is the problem with the code? – Nina Scholz Jan 08 '20 at 20:23
  • Your approach is clean and simple. Unless you're looking for performance gains, it's ideal IMO. You could potentially replace the 4 line sort predicate with the 2 lines: `let field = fieldNames.find(field => a[field] !== b[field]); return field ? a[field].localeCompare(b[field]) : 0;` But this would only work for string values. – junvar Jan 08 '20 at 20:26

1 Answers1

1

Your solution seems good to me, I would add a final "return 0" outside of the for loop to cover the situation where the objects being compared are identical. Other than that I think you have it covered.

John D
  • 58
  • 5
  • 1
    Good call. Also prevents a console log warning saying `Expected to return a value at the end of arrow function` – Johnny Metz Jan 10 '20 at 02:26