Explain Codes LogoExplain Codes Logo

Sort objects in an array alphabetically on one property of the array

javascript
sort
comparator
localecompare
Nikita BarsukovbyNikita Barsukov·Nov 20, 2024
TLDR

To sort an array of objects by a property alphabetically using .sort() with localeCompare, check out the following chunk of code:

let items = [{ name: "Edward" }, { name: "Sharpe" }, { name: "Zeros" }]; items.sort((a, b) => a.name.localeCompare(b.name));

This piece of code leverages string comparison to arrange the name property alphabetically.

Diving into sort() and localeCompare

To tinker with simple arrays and complex objects, sort() is your best bet. When fiddling with objects, we must point out the property that needs to be sorted. This property is reachable with dot notation, like, a.DepartmentName fetches the DepartmentName property of object a.

To get around the quirkiness of case sensitivity affecting the kind of order you get, spice up your code with toUpperCase() or toLowerCase(). This ensures case-insensitivity when sorting—absolutely useful when users are leaning on their expectations for 'apple' and 'Apple' to appear together.

items.sort((a, b) => a.name.toUpperCase().localeCompare(b.name.toUpperCase()));

// Remember, cases matter after all!

Understand that return values -1, 0, or +1, are key to your sorting logic. To decode these return values, if a should appear before b, the system emits -1; if both a and b are to remain in their places, it returns 0; and if a nudges b to take up the next position, it will return +1.

Leveling up with complex sorting scenarios

Multi-layered sorting

There can be situations where we want to sort by one property, then by another if the first spell out equals. Our comparator function is flexible and can handle such nuanced cases pretty well:

items.sort((a, b) => { let comparison = a.department.localeCompare(b.department); if (comparison !== 0) return comparison; return a.name.localeCompare(b.name); });

Adventures with non-string properties

However, what if our property being sorted isn't a string but a number or a date? Fear not, a small tweak, and it will work just as smoothly:

items.sort((a, b) => a.id - b.id); // Numerical sort

// Who said numbers can't dance?

Internationalization at its best

In case you are trying to charm an international audience, we need to factor in the peculiarities of local linguistic rules. Thankfully, localeCompare provides a hiding place for Intl.Collator to deal with such situations, ensuring our sort method abides by a global cultural etiquette.

Experiment with custom comparators for added versatility

Arrow functions for a cleaner code

ES6 arrow functions can drastically simplify our sort comparator:

items.sort((a, b) => a.rank.localeCompare(b.rank));

// The sorter has a new arrow in its quiver!

Arrow functions make your code more readable by simplifying the function scope.

Dealing with undefined or null values

There will be times when a property can be undefined or null. Due to our careful crafting, our compare function will handle these cases and prevent errors from crashing your party during sorting:

items.sort((a, b) => (a.name || '').localeCompare(b.name || ''));

// Undefined properties? Bring it on!

Compatibility with the new keyword

Handling objects created with the new keyword might be tricky as they might have some prototype properties tacked on. Make sure your sort operation targets own properties:

function Employee(name) { this.name = name; } let employees = [new Employee("Alice"), new Employee("Bob")]; employees.sort((a, b) => a.name.localeCompare(b.name));

Test and sculpt your code to perfection

Before you close those curly braces, test different cases—empty strings, multi-level sorts, and accented characters. Use online code playgrounds like CodePen or JSFiddle to flaunt your code and invite peer review. Testing is the holy grail to ensure your sorting logic is robust.