How to Sort Arrays and Arrays of Objects in JavaScript
Sorting arrays is a common task in JavaScript, whether you are working with numbers, strings, or complex objects. JavaScript offers various methods to sort arrays, allowing you to modify the original array, create a sorted copy, or apply custom sorting logic. This guide explores different techniques for sorting both simple arrays and arrays of objects efficiently.
Contents
Live Demo: Online JavaScript Array Sorting Tool
This tool helps you quickly sort arrays in Ascending or Descending order. It supports various data types, including simple arrays, arrays of objects, numeric arrays, mixed arrays, and date arrays. Optimized for large datasets, the tool can handle sorting millions of array values efficiently.
Enter your array or plain text name list in the input box below, then click the "Sort" button to instantly see the sorted results.
- Select Data Type: Choose from JavaScript Array/Object, Plain Text Lists, or Delimited Formats.
- Add Your Data: Enter your data in the input code editor or upload a file.
- Set Options: Choose Sort Order (Ascending/Descending), Case Sensitivity, and Language for locale-based sorting.
- Sort the Data: Click the "Sort" button to process the sorting.
- Copy or Download: Once sorted, copy the result or download the sorted data as a file.
Select your data type code:
Add sample data or arrays:
Options:
Contains Dates:
["2025-2-10", "15/2/2025"]
undefined
, null
values to appear first or last after sortingSort order type:
Output Format:
Result:
Supported Formats:
JavaScript Arrays (including arrays of objects)
Plain text name lists (one entry per line)
Delimited formats (comma
,
, colon:
, semicolon;
separated values)
Advanced Sorting Options:
Object Sorting: Sort arrays of objects by specific keys, including nested keys (e.g.,
name
,name.first
,name.last
).Date Sorting: Sort arrays containing date values in chronological order.
Sort Order Options: Choose between Ascending or Descending order.
Case First Sorting: Control whether uppercase or lowercase letters appear first or last.
Data Type Positioning: Define whether
Boolean
,undefined
, andnull
values should appear first or last after sorting.Locale-Based Sorting: Supports language-specific sorting for different alphabets and character sets.
File Upload:
Drag and Drop: Upload files effortlessly by dragging and dropping them into the tool.
File Selection: Use the file upload option to select and process files directly from your device.
Data Integrity:
Preserve Original Array: Generates a new sorted array without modifying the original data.
Export Options:
Export Options: Download or copy the sorted array/code with a single click.
Performance:
Optimized for Large Datasets: Tested with JavaScript arrays containing 1.2 million words, sorted in 2 to 5 minutes (performance may vary based on device capabilities).
Non-Blocking UI: Sorting large datasets without freezing the user interface, ensuring a smooth user experience.
Visualization:
Live Sorting Preview: Displays progress and estimated time for sorting large datasets without freezing the UI.
The difference between array.sort() and array.toSorted() in JavaScript is:
1. sort() (Mutates the Original Array)
The sort() method sorts an array in place, meaning it modifies the original array.
- The
.sort()
method modifies the original array in place. - It sorts elements lexicographically by default (converting to strings).
- You can pass a custom comparator function for more control.
- Since it mutates the original array, it can cause unintended side effects.
Example:
2. toSorted() (Returns a New Sorted Array)
ES2023 introduced toSorted(), which works like sort(), but returns a new sorted array without modifying the original.
- The
.toSorted()
method does not modify the original array. - It returns a new sorted array instead.
- It behaves similarly to
.sort()
, but ensures immutability. - Introduced in ES2023, so it may not be available in older browsers.
Example:
When to Use Which?
- Use
.sort()
when you want to sort in place and don't need the original order. - Use
.toSorted()
when you need to preserve the original array and work with a sorted copy.
To sort a simple array of numbers in ascending or descending order, you can use the built-in sort()
method with a custom compare function. Here is how to create a flexible sorting function:
const sortArray = (arr, order = 'asc') => {
if (!Array.isArray(arr)) {
throw new Error('Input must be an array');
}
// Create a copy to avoid mutating the original array. [...arr]
return [...arr].sort((a, b) => {
if (order === 'desc') {
return b - a; // Descending order
} else {
return a - b; // Ascending order
}
});
};
Example usage:
// Example usage:
const numbers = [5, 2, 9, 1, 5, 6];
// Ascending order
console.log(sortArray(numbers, 'asc'));
// Output: [1, 2, 5, 5, 6, 9]
// Descending order
console.log(sortArray(numbers, 'desc'));
// Output: [9, 6, 5, 5, 2, 1]
Features:
- Error Handling: The function checks if the input is an array and validates the sort order.
- Default Order: If no order is specified, it defaults to ascending.
- Does not modify the original array.
Sorting arrays of objects is slightly more complex because you need to specify the key to sort by. Here is a versatile function that sorts objects based on a given key, with support for both ascending and descending order.
const sortObjectArray = (arr, key, order = 'asc') => {
if (!Array.isArray(arr)) {
throw new Error('Input must be an array');
}
return arr.sort((a, b) => {
if (!(key in a) || !(key in b)) {
throw new Error(`Key "${key}" does not exist in one or more objects`);
}
if (typeof a[key] === 'number' && typeof b[key] === 'number') {
return order === 'asc' ? a[key] - b[key] : b[key] - a[key];
} else {
const valA = a[key].toString().toLowerCase();
const valB = b[key].toString().toLowerCase();
if (valA < valB) return order === 'asc' ? -1 : 1;
if (valA > valB) return order === 'asc' ? 1 : -1;
return 0;
}
});
};
Example usage:
// Example usage:
const people = [
{ name: 'Riya', age: 30 },
{ name: 'Surya', age: 25 },
{ name: 'Boby', age: 35 },
];
// Sort by age (ascending)
console.log(sortObjectArray(people, 'age', 'asc'));
// Output: [{'name':'Surya','age':25}, {'name':'Riya','age':30}, {'name':'Boby','age':35}]
// Sort by name (descending)
console.log(sortObjectArray(people, 'name', 'desc'));
// Output: [{'name':'Surya','age':25}, {'name':'Riya','age':30}, {'name':'Boby','age':35}]
Features:
- Flexible Key Sorting: You can sort by any key in the object.
- Type Handling: Automatically detects whether the key holds numbers or strings.
- Case Insensitive Sorting: Converts strings to lowercase to ensure case-insensitive sorting.
- Error Handling: Checks if the key exists in the objects.
This function sorts arrays containing both numbers and strings with flexible sorting logic. Numbers are sorted numerically and placed before strings, while strings are sorted alphabetically in a case-insensitive manner. This ensures consistent and predictable ordering, regardless of the data type mix in the array.
const mixedArraySort = (arr, options = {}) => {
const {
descending = false
} = options;
const sortMultiplier = descending ? -1 : 1;
// Create a copy to avoid mutating the original array
return [...arr].sort((a, b) => {
// Handle null and undefined values
if (a == null) return descending ? -1 : 1;
if (b == null) return descending ? 1 : -1;
// Attempt to convert to numbers, with robust type handling
const numA = typeof a === 'number' ? a : Number(a);
const numB = typeof b === 'number' ? b : Number(b);
// Check if both values can be converted to valid numbers
const isNumA = typeof numA === 'number' && !isNaN(numA);
const isNumB = typeof numB === 'number' && !isNaN(numB);
// Sort numbers numerically
if (isNumA && isNumB) {
return sortMultiplier * (numA - numB);
}
// Numbers come before strings (adjusted for descending order)
if (isNumA) return descending ? 1 : -1;
if (isNumB) return descending ? -1 : 1;
// Sort strings case-insensitively
return sortMultiplier * String(a).localeCompare(String(b), undefined, {
sensitivity: 'base',
numeric: true // Handle numeric strings more intelligently
});
});
};
Example usage:
// Example usage
console.log("Ascending order (default):");
console.log(mixedArraySort([3, 'a', 2, 'B', 10, 1, 'c']));
// Output: [1, 2, 3, 10, 'a', 'B', 'c']
console.log("\nDescending order:");
console.log(mixedArraySort([3, 'a', 2, 'B', 10, 1, 'c'], { descending: true }));
// Output: ['c', 'B', 'a', 10, 3, 2, 1]
// More examples to demonstrate flexibility
const mixedArray = [3, 'apple', 2, 'Banana', 10, 1, 'cherry'];
console.log("\nAscending order mixed array:");
console.log(mixedArraySort(mixedArray));
console.log("\nDescending order mixed array:");
console.log(mixedArraySort(mixedArray, { descending: true }));
Features:
- Sorts numbers and strings intelligently.
- Supports ascending and descending order.
- Converts numeric strings and prioritizes numbers.
- Case-insensitive string sorting with
localeCompare
. - Handles null and undefined values consistently.
- Does not modify the original array.
When dealing with deeply nested objects, sorting requires accessing nested properties. The following function allows sorting based on a nested property path (e.g., address.city
).
const sortNestedObjectArray = (arr, path, order = 'asc') => {
// Validate input array
if (!Array.isArray(arr)) {
throw new TypeError('Expected an array of objects to sort.');
}
// Validate path
if (typeof path !== 'string' || path.trim() === '') {
throw new Error('Path must be a non-empty string.');
}
// Validate order
if (order !== 'asc' && order !== 'desc') {
throw new Error('Order must be either "asc" or "desc".');
}
// Helper function to retrieve nested values safely
const getNestedValue = (obj, path) => path.split('.').reduce((o, key) => o?.[key], obj);
return arr.sort((a, b) => {
const valA = getNestedValue(a, path);
const valB = getNestedValue(b, path);
// Handle cases where the property does not exist
if (valA === undefined || valB === undefined) {
throw new Error(`Path "${path}" does not exist in one or more objects.`);
}
// Sort numbers in ascending or descending order
if (typeof valA === 'number' && typeof valB === 'number') {
return order === 'asc' ? valA - valB : valB - valA;
}
// Sort strings using localeCompare for proper ordering
return order === 'asc' ?
valA.toString().localeCompare(valB.toString()) :
valB.toString().localeCompare(valA.toString());
});
};
Example usage:
// Example usage:
const users = [
{ name: 'Alice', address: { city: 'Seattle' } },
{ name: 'Bob', address: { city: 'Austin' } },
{ name: 'Charlie', address: { city: 'Denver' } },
];
console.log(sortNestedObjectArray(users, 'address.city', 'asc'));
// Output: [
// { name: 'Bob', address: { city: 'Austin' } },
// { name: 'Charlie', address: { city: 'Denver' } },
// { name: 'Alice', address: { city: 'Seattle' } }
// ]
Features:
- Nested Property Sorting: Sort by deeply nested keys using dot notation (e.g.,
address.city
). - Comprehensive Validation: Validates the array, path, and order inputs.
- Locale-Aware String Sorting: Uses
localeCompare
for proper alphabetical sorting, respecting different locales. - Error Handling: Throws errors if the path does not exist in one or more objects.
This function sorts an array by placing even numbers before odd numbers, and sorts each group in ascending order. It handles negative numbers correctly.
/* Sorts an array by placing even numbers before odd numbers. */
const sortEvenBeforeOdd = (arr) => {
// Create a copy to avoid mutating the original array
return [...arr].sort((a, b) => {
// Separate computation of parity and value comparison
const parityA = Math.abs(a) % 2;
const parityB = Math.abs(b) % 2;
// First, compare by parity (even numbers first)
if (parityA !== parityB) {
return parityA - parityB;
}
// If parity is the same, sort by value
return a - b;
});
};
Example usage:
// Example Usage:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(sortEvenBeforeOdd(numbers));
// Expected Output: [2, 4, 6, 8, 1, 3, 5, 7, 9]
const negativeNumbers = [3, 1, 2, -4, -7, 6, 8, -5];
console.log(sortEvenBeforeOdd(negativeNumbers));
// Expected Output: [-4, 2, 6, 8, -7, -5, 1, 3]
For sorting strings in different languages, you can use Intl.Collator
to ensure correct alphabetical order according to language-specific rules.
const localeSort = (arr, options = {}) => {
const {
locale = 'en',
order = 'asc',
collatorOptions = {}
} = options;
// Modify collator options to ensure case handling
const finalCollatorOptions = {
sensitivity: 'variant', // Most sensitive comparison
...collatorOptions // Allow override of default options
};
const collator = new Intl.Collator(locale, finalCollatorOptions);
return [...arr].sort((a, b) => {
// Convert to string and handle potential non-string inputs
const stringA = String(a);
const stringB = String(b);
// for array of object
// const key = 'name'; // your object key name here
// const stringA = String(a[key]);
// const stringB = String(b[key]);
// Compare with the configured collator
const result = collator.compare(stringA, stringB);
// Apply order (ascending or descending)
return order === 'asc' ? result : -result;
});
};
Example usage:
// Examples
const wordList = [
'café', 'cafe', 'Café', 'CAFE',
'résumé', 'resume', 'Résumé',
'apple', 'Apple', 'APPLE'
];
// Default English sort
console.log('Default sort:', localeSort(wordList));
// Swedish locale (different letter ordering)
console.log('Swedish locale:', localeSort(wordList, {
locale: 'sv'
}));
// Descending order
console.log('Descending order:', localeSort(wordList, { order: 'desc' }));
// Uppercase first
const upperFirst = localeSort(wordList, {
order: 'asc',
locale: 'en',
collatorOptions: {
caseFirst: 'upper'
}
});
console.log('Uppercase first:', upperFirst);
// Mixed type array
const mixedList = [1, 'a', 'B', 2, 'C', 10];
console.log('Mixed list sort:', localeSort(mixedList));
The Intl.Collator
constructor accepts an optional configuration object that allows fine-tuning of string comparisons across different locales. Here's a comprehensive breakdown:
const collatorOptions = {
// Controls how characters with diacritical marks are compared
sensitivity: 'base' | 'accent' | 'case' | 'variant',
// Determines how different letter cases are handled
caseFirst: 'upper' | 'lower' | 'false',
// Ignore punctuation during comparison
ignorePunctuation: true | false,
// Numeric comparison mode
numeric: true | false
};
collatorOptions examples
Sensitivity Comparison:
base: ["apple","Apple","APPLE","café","cafe","Café","CAFE","résumé","resume","Résumé"]
accent: ["apple","Apple","APPLE","cafe","CAFE","café","Café","resume","résumé","Résumé"]
case: ["apple","Apple","APPLE","café","cafe","Café","CAFE","résumé","resume","Résumé"]
variant: ["apple","Apple","APPLE","cafe","CAFE","café","Café","resume","résumé","Résumé"]
Case First Comparison:
default: ["apple","Apple","APPLE","cafe","CAFE","café","Café","resume","résumé","Résumé"]
upper: ["APPLE","Apple","apple","CAFE","cafe","Café","café","resume","Résumé","résumé"]
lower: ["apple","Apple","APPLE","cafe","CAFE","café","Café","resume","résumé","Résumé"]
Punctuation Handling:
const array = ['co-op', 'coop', 'co op'];
with punctuation: ["co op","co-op","coop"]
ignore punctuation: ["co-op","coop","co op"]
Numeric Sorting:
default: ["1","10","2","20","3"]
numeric: ["1","2","3","10","20"]
Key Features:
- Locale-Sensitive Sorting: Accurately sorts strings using language-specific comparison rules
- Flexible Configuration: Supports custom locale settings, sorting order, and advanced comparison options
- Diacritical Mark Handling: Intelligent handling of accented characters and special characters
- Case and Accent Sensitivity Controls: Fine-tune sorting with multiple sensitivity levels
This function sort arrays containing date strings or Date objects with robust error handling and customizable sorting options. This method ensures accurate chronological ordering
const sortDates = (datesArray, options = {}) => {
// Default options
const {
ascending = true,
} = options;
// Input validation
if (!Array.isArray(datesArray)) {
throw new TypeError('Input must be an array');
}
const validateDate = date => {
if (typeof date === 'number') {
const timestamp = new Date(date);
return isNaN(timestamp.getTime()) ? null : timestamp;
}
if (typeof date === 'string') {
// Handle ISO 8601 dates and other common formats
const parsed = new Date(date);
if (!isNaN(parsed.getTime())) {
return parsed;
}
return null;
}
return null;
};
// Create a copy to avoid mutating the original array
const sortableArray = [...datesArray];
return sortableArray.sort((a, b) => {
const dateA = validateDate(a);
const dateB = validateDate(b);
// Handle cases where both dates are invalid
if (!dateA && !dateB) return 0;
// Normal date comparison
const comparison = dateA.getTime() - dateB.getTime();
return ascending ? comparison : -comparison;
});
};
Example usage:
// Example usage:
// Basic usage
const dates1 = ['2023-01-15', '2022-05-20', '2024-03-10'];
console.log(sortDates(dates1)); // Ascending order by default
// Descending order
const dates2 = ['2023-01-15', '2022-05-20', '2024-03-10'];
console.log(sortDates(dates2, { ascending: false }));