Сортировать массив по имени (в алфавитном порядке) в Javascript
Я получил массив (см. Ниже для одного объекта в массиве), который мне нужно отсортировать по имени, используя JavaScript. Как мне это сделать?
var user = {
bio: null,
email: "user@domain.com",
firstname: "Anna",
id: 318,
lastAvatar: null,
lastMessage: null,
lastname: "Nickson",
nickname: "anny"
};
17 ответов
Предположим, у вас есть массив users
, Вы можете использовать users.sort
и передать функцию, которая принимает два аргумента и сравнить их (компаратор)
Должно вернуться
- что-то отрицательное, если первый аргумент меньше второго (должен быть помещен перед вторым в результирующем массиве)
- что-то положительное, если первый аргумент больше (должен быть помещен после второго)
- 0, если эти два элемента равны.
В нашем случае, если два элемента a
а также b
мы хотим сравнить a.firstname
а также b.firstname
Пример:
users.sort(function(a, b){
if(a.firstname < b.firstname) { return -1; }
if(a.firstname > b.firstname) { return 1; }
return 0;
})
Этот код будет работать с любым типом.
Обратите внимание, что в "реальной жизни"™ вы часто хотите игнорировать регистр, правильно сортировать диакритические знаки, странные символы, такие как ß и т. Д. При сравнении строк, поэтому вы можете захотеть использовать localeCompare
, Смотрите другие ответы для ясности.
Кратчайший код с ES6!
users.sort((a, b) => a.firstname.localeCompare(b.firstname))
Базовая поддержка String.prototype.localeCompare() универсальна!
Что-то вроде этого:
array.sort(function(a, b){
var nameA=a.name.toLowerCase(), nameB=b.name.toLowerCase();
if (nameA < nameB) //sort string ascending
return -1;
if (nameA > nameB)
return 1;
return 0; //default return value (no sorting)
});
Если сравниваемые строки содержат символы Юникода, вы можете использовать localeCompare
функция String
класс как следующий:
users.sort(function(a,b){
return a.firstname.localeCompare(b.firstname);
})
Милый маленький ES6 один лайнер:
users.sort((a, b) => a.firstname !== b.firstname ? a.firstname < b.firstname ? -1 : 1 : 0);
Мы можем использовать localeCompare, но нам также нужно проверить ключи на значения Falsey
Код ниже не будет работать, если в одной записи отсутствует lname.
obj.sort((a, b) => a.lname.localeCompare(b.lname))
Таким образом, мы должны проверить значение Falsey, как показано ниже
let obj=[
{name:'john',lname:'doe',address:'Alaska'},
{name:'tom',lname:'hopes',address:'California'},
{name:'harry',address:'Texas'}
]
let field='lname';
console.log(obj.sort((a, b) => (a[field] || "").toString().localeCompare((b[field] || "").toString())));
ИЛИ ЖЕ
мы можем использовать lodash, это очень просто. Он обнаружит возвращенные значения, т.е. число или строку, и выполнит сортировку соответственно.
import sortBy from 'lodash/sortBy';
sortBy(obj,'name')
http://underscorejs.org/ предлагает очень хорошую функцию _.sortBy:
_.sortBy([{a:1},{a:3},{a:2}], "a")
или вы можете использовать пользовательскую функцию сортировки:
_.sortBy([{a:"b"},{a:"c"},{a:"a"}], function(i) {return i.a.toLowerCase()})
В случае, если мы сортируем имена или что-то со специальными символами, такими как ñ или áéíóú (обыкновенные по-испански), мы могли бы использовать параметры params locales (в данном случае es для испанского языка) и такие параметры:
let user = [{'firstname': 'Az'},{'firstname': 'Áb'},{'firstname':'ay'},{'firstname': 'Ña'},{'firstname': 'Nz'},{'firstname': 'ny'}];
user.sort((a, b) => a.firstname.localeCompare(b.firstname, 'es', {sensitivity: 'base'}))
console.log(user)
Официальные варианты локали можно найти здесь: iana, es (испанский), de (немецкий), fr (французский). О чувствительности базовых средств:
Только строки, отличающиеся базовыми буквами, сравниваются как неравные. Примеры: a ≠ b, a = á, a = A.
Более компактная запись:
user.sort(function(a, b){
return a.firstname == b.firstname ? 0 : a.firstname < b.firstname ? -1 : 1;
})
Я удивлен, что никто не упомянул Collators. Вы не должны использовать
localeCompare
если вам не нужно, так как он имеет значительно худшую производительность.
const collator = new Intl.Collator('zh-CN', { // Chinese Simplified for example
numeric: true,
sensitivity: 'base',
});
function sortAsc(a, b) {
if (typeof a === 'string' && typeof b === 'string') {
return collator.compare(b, a)
}
return b - a;
}
function sortDesc(a, b) {
if (typeof a === 'string' && typeof b === 'string') {
return collator.compare(a, b);
}
return a - b;
}
По сути, вы можете сортировать массивы с помощью метода sort, но если вы хотите отсортировать объекты, вам нужно передать функцию для сортировки метода массива, поэтому я приведу пример использования вашего массива.
user = [{
bio: "<null>",
email: "user@domain.com",
firstname: 'Anna',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
},
{
bio: "<null>",
email: "user@domain.com",
firstname: 'Senad',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
},
{
bio: "<null>",
email: "user@domain.com",
firstname: 'Muhamed',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
}];
var ar = user.sort(function(a, b)
{
var nA = a.firstname.toLowerCase();
var nB = b.firstname.toLowerCase();
if(nA < nB)
return -1;
else if(nA > nB)
return 1;
return 0;
});
Вдохновленный этим ответом,
users.sort((a,b) => (a.firstname - b.firstname));
Пытаться
users.sort((a,b)=> (a.firstname>b.firstname)*2-1)
var users = [
{ firstname: "Kate", id: 318, /*...*/ },
{ firstname: "Anna", id: 319, /*...*/ },
{ firstname: "Cristine", id: 317, /*...*/ },
]
console.log(users.sort((a,b)=> (a.firstname>b.firstname)*2-1) );
Обобщенная функция может быть написана как ниже
function getSortedData(data, prop, isAsc) {
return data.sort((a, b) => (a[prop] < b[prop] ? -1 : 1) * (isAsc ? 1 : -1));
}
Вы можете передать следующие параметры
- Данные, которые вы хотите отсортировать
- Свойство в данных по нему должно быть отсортировано
- Последний параметр имеет логический тип. Он проверяет, хотите ли вы сортировать по возрастанию или по убыванию
Также для сортировки asec и desc, вы можете использовать это: предположим, у нас есть переменная SortType, которая задает сортировку по возрастанию или по убыванию, которую вы хотите:
users.sort(function(a,b){
return sortType==="asc"? a.firstName.localeCompare( b.firstName): -( a.firstName.localeCompare( b.firstName));
})
Просто для записи, если вы хотите иметь именованную функцию сортировки, синтаксис следующий:
let sortFunction = (a, b) => {
if(a.firstname < b.firstname) { return -1; }
if(a.firstname > b.firstname) { return 1; }
return 0;
})
users.sort(sortFunction)
Обратите внимание, что следующее НЕ работает:
users.sort(sortFunction(a,b))
Проще говоря, вы можете использовать этот метод
users.sort(function(a,b){return a.firstname < b.firstname ? -1 : 1});
Вы можете использовать это для объектов
transform(array: any[], field: string): any[] {
return array.sort((a, b) => a[field].toLowerCase() !== b[field].toLowerCase() ? a[field].toLowerCase() < b[field].toLowerCase() ? -1 : 1 : 0);}
Сложил верхние ответы в прототип для сортировки по ключу.
Array.prototype.alphaSortByKey= function (key) {
this.sort(function (a, b) {
if (a[key] < b[key])
return -1;
if (a[key] > b[key])
return 1;
return 0;
});
return this;
};
Вы можете использовать метод встроенного массива - sort
, Этот метод принимает метод обратного вызова в качестве параметра
// custom sort function to be passed as param/callback to the Array's sort method
function myCustomSort(a, b) {
return (a.toLowerCase() > b.toLowerCase()) ? 1 : -1;
}
// Actual method to be called by entity that needs sorting feature
function sortStrings() {
var op = Array.prototype.sort.call(arguments, myCustomSort);
}
// Testing the implementation
var sortedArray = sortStrings("Burger", "Mayo1", "Pizza", "boxes", "Apples", "Mayo");
console.log(sortedArray); //["Apples", "boxes", "Burger", "Mayo", "Mayo1", "Pizza"]
Ключевые моменты, которые следует отметить для понимания этого кода.
- Пользовательский метод, в этом случае,
myCustomSort
, должен возвращать +1 или -1 для каждой пары элементов (из входного массива) сравнения. - использование
toLowerCase()
/toUpperCase()
в пользовательском методе обратного вызова сортировки, чтобы различие в регистре не влияло на правильность процесса сортировки.
Я надеюсь, что это достаточно четкое объяснение. Не стесняйтесь комментировать, если вы думаете, нужна дополнительная информация.
Ура!
Моя реализация отлично работает в более старых версиях ES:
sortObject = function(data) {
var keys = Object.keys(data);
var result = {};
keys.sort();
for(var i = 0; i < keys.length; i++) {
var key = keys[i];
result[key] = data[key];
}
return result;
};
Для сортировки по двум факторам (имя и фамилия):
users.sort((a, b) => a.name.toLowerCase() < b.name.toLowerCase() ? -1 : a.name.toLowerCase() > b.name.toLowerCase() ? 1 : a.lastname.toLowerCase() < b.lastname.toLowerCase() ? -1 : a.lastname.toLowerCase() > b.lastname.toLowerCase() ? 1 : 0)
Вы можете использовать что-то подобное, чтобы избавиться от чувствительности к регистру
users.sort(function(a, b){
//compare two values
if(a.firstname.toLowerCase() < b.firstname.toLowerCase()) return -1;
if(a.firstname.toLowerCase() > b.firstname.toLowerCase()) return 1;
return 0;
})