Сортировать массив объектов по значению свойства строки

У меня есть массив объектов JavaScript:

var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];

Как я могу отсортировать их по значению last_nom в JavaScript?

Я знаю о sort(a,b), но это только кажется, работает на строки и числа. Нужно ли добавлять toString() метод для моих объектов?

62 ответа

Решение

Достаточно просто написать собственную функцию сравнения:

function compare(a,b) {
  if (a.last_nom < b.last_nom)
    return -1;
  if (a.last_nom > b.last_nom)
    return 1;
  return 0;
}

objs.sort(compare);

Или встроенный (с Марко Демайо):

objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0)); 

Вы также можете создать динамическую функцию сортировки, которая сортирует объекты по значению, которое вы передаете:

function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

Таким образом, вы можете иметь массив таких объектов:

var People = [
    {Name: "Name", Surname: "Surname"},
    {Name:"AAA", Surname:"ZZZ"},
    {Name: "Name", Surname: "AAA"}
];

... и это будет работать, когда вы делаете:

People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));

На самом деле это уже отвечает на вопрос. Ниже написано, что со мной связались многие, жалуясь, что он не работает с несколькими параметрами.

Несколько параметров

Вы можете использовать функцию ниже для генерации функций сортировки с несколькими параметрами сортировки.

function dynamicSortMultiple() {
    /*
     * save the arguments object as it will be overwritten
     * note that arguments object is an array-like object
     * consisting of the names of the properties to sort by
     */
    var props = arguments;
    return function (obj1, obj2) {
        var i = 0, result = 0, numberOfProperties = props.length;
        /* try getting a different result from 0 (equal)
         * as long as we have extra properties to compare
         */
        while(result === 0 && i < numberOfProperties) {
            result = dynamicSort(props[i])(obj1, obj2);
            i++;
        }
        return result;
    }
}

Что позволит вам сделать что-то вроде этого:

People.sort(dynamicSortMultiple("Name", "-Surname"));

Добавление его в прототип

(Реализация, которая чуть ниже вдохновлена ответом Mike R)

Я бы не рекомендовал менять собственный прототип объекта, а просто привести пример, чтобы вы могли реализовать его на своих собственных объектах (Для сред, которые его поддерживают, вы также можете использовать Object.defineProperty, как показано в следующем разделе, который по крайней мере не имеет отрицательного побочного эффекта перечисления, как описано в последней части)

Реализация прототипа будет выглядеть примерно так ( вот рабочий пример):

//Don't just copy-paste this code. You will break the "for-in" loops
!function() {
    function _dynamicSortMultiple(attr) {
       /* dynamicSortMultiple function body comes here */
    }
    function _dynamicSort(property) {
        /* dynamicSort function body comes here */
    }
    Array.prototype.sortBy = function() {
        return this.sort(_dynamicSortMultiple.apply(null, arguments));
    }
}();

"ОК" способ добавить его к прототипу

Если вы ориентируетесь на IE v9.0 и выше, то, как я уже упоминал, используйте Object.defineProperty следующим образом ( рабочий пример):

//Won't work below IE9, but totally safe otherwise
!function() {
    function _dynamicSortMultiple(attr) {
       /* dynamicSortMultiple function body comes here */
    }
    function _dynamicSort(property) {
        /* dynamicSort function body comes here */
    }
    Object.defineProperty(Array.prototype, "sortBy", {
        enumerable: false,
        writable: true,
        value: function() {
            return this.sort(_dynamicSortMultiple.apply(null, arguments));
        }
    });
}();

Это может быть приемлемым компромиссом, пока не прибудет оператор связывания.

Все эти прототипы веселья позволяют это:

People.sortBy("Name", "-Surname");

Вы должны прочитать это

Если вы используете метод прямого доступа к прототипу (Object.defineProperty в порядке), а другой код не проверяет hasOwnProperty, котята умирают! Ладно, если честно, ни один котенок не причинит никакого вреда, но, вероятно, что-то сломается, и любой другой разработчик в вашей команде будет вас ненавидеть

злой

Видите этот последний "SortBy"? Да уж. Не круто. Используйте Object.defineProperty, где вы можете, и оставьте Array.prototype один, в противном случае.

В ES6/ES2015 или новее вы можете сделать это так:

objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));

http://underscorejs.org/

используйте подчеркивание, его маленький и удивительный...

sortBy_.sortBy (list, iterator, [context]) Возвращает отсортированную копию списка, ранжированного в порядке возрастания по результатам выполнения каждого значения через итератор. Итератор также может быть строковым именем свойства для сортировки (например, длина).

var objs = [ 
  { first_nom: 'Lazslo',last_nom: 'Jamf' },
  { first_nom: 'Pig', last_nom: 'Bodine'  },
  { first_nom: 'Pirate', last_nom: 'Prentice' }
];

var sortedObjs = _.sortBy( objs, 'first_nom' );

Не понимаю, почему люди делают это так сложно:

objs.sort(function(a, b){
  return a.last_nom > b.last_nom;
});

Для более строгих двигателей:

objs.sort(function(a, b){
  return a.last_nom == b.last_nom ? 0 : +(a.last_nom > b.last_nom) || -1;
});

Поменяйте местами оператор, чтобы отсортировать его в обратном алфавитном порядке.

С учетом регистра

      arr.sort((a, b) => a.name > b.name ? 1 : -1);

Без учета регистра

      arr.sort((a, b) => a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1);

Если нет изменений в порядке тех же строк, возвращается -1 не будет иметь никакого эффекта, или вы можете использовать >= оператор

Если у вас есть повторяющиеся фамилии, вы можете отсортировать их по имени-

obj.sort(function(a,b){
  if(a.last_nom< b.last_nom) return -1;
  if(a.last_nom >b.last_nom) return 1;
  if(a.first_nom< b.first_nom) return -1;
  if(a.first_nom >b.first_nom) return 1;
  return 0;
});

По состоянию на 2018 год существует гораздо более короткое и элегантное решение. Просто используйте. Array.prototype.sort ().

Пример:

var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: 'Magnetic', value: 13 },
  { name: 'Zeros', value: 37 }
];

// sort by value
items.sort(function (a, b) {
  return a.value - b.value;
});

Простое и быстрое решение этой проблемы с использованием наследования прототипа:

Array.prototype.sortBy = function(p) {
  return this.slice(0).sort(function(a,b) {
    return (a[p] > b[p]) ? 1 : (a[p] < b[p]) ? -1 : 0;
  });
}

Пример / Использование

objs = [{age:44,name:'vinay'},{age:24,name:'deepak'},{age:74,name:'suresh'}];

objs.sortBy('age');
// Returns
// [{"age":24,"name":"deepak"},{"age":44,"name":"vinay"},{"age":74,"name":"suresh"}]

objs.sortBy('name');
// Returns
// [{"age":24,"name":"deepak"},{"age":74,"name":"suresh"},{"age":44,"name":"vinay"}]

Обновление: больше не изменяет исходный массив.

У меня есть кусок кода, который работает для меня:

arr.sort((a, b) => a.name > b.name)

ОБНОВЛЕНИЕ: не работает всегда, поэтому это не правильно:(

Lodash.js (расширенный набор http://underscorejs.org/)

Хорошо не добавлять фреймворк для каждой простой логики, но полагаться на хорошо протестированные сервисные фреймворки, ускорить разработку и уменьшить количество написанных ошибок - не стыдно.

Lodash производит очень чистый код и продвигает более функциональный стиль программирования, что приводит к меньшему количеству ошибок. Одним взглядом становится ясно, каково намерение, если код.

Проблема ОП может быть просто решена как:

const sortedObjs = _.sortBy(objs, 'last_nom');

Больше информации? Например, у нас есть следующий вложенный объект:

const users = [
  { 'user': {'name':'fred', 'age': 48}},
  { 'user': {'name':'barney', 'age': 36 }},
  { 'user': {'name':'wilma'}},
  { 'user': {'name':'betty', 'age': 32}}
];

Теперь мы можем использовать сокращение _.property user.age указать путь к свойству, которое должно быть сопоставлено. Мы отсортируем пользовательские объекты по вложенному свойству age. Да, он позволяет сопоставлять вложенные свойства!

const sortedObjs = _.sortBy(users, ['user.age']);

Хотите, чтобы это было наоборот? Нет проблем. Используйте _.reverse.

const sortedObjs = _.reverse(_.sortBy(users, ['user.age']));

Хотите объединить оба с помощью цепочки вместо?

const sortedObjs = _.chain(users).sortBy('user.age').reverse().value();

Ты можешь использовать

Самый простой способ: Lodash

( https://lodash.com/docs/4.17.10#orderBy)

Этот метод похож на _.sortBy, за исключением того, что он позволяет указывать порядок сортировки итерируемых для сортировки. Если заказы не указаны, все значения сортируются в порядке возрастания. В противном случае укажите порядок "desc" для убывающего или "asc" для возрастающего порядка сортировки соответствующих значений.

аргументы

collection (Array|Object): коллекция для повторения. [iteratees=[_.identity]] (Array[]|Function[]|Object[]|string[]): Итерации для сортировки. [orders] (string[]): порядок сортировки итераций.

Возвращает

(Массив): возвращает новый отсортированный массив.


var _ = require('lodash');
var homes = [
    {"h_id":"3",
     "city":"Dallas",
     "state":"TX",
     "zip":"75201",
     "price":"162500"},
    {"h_id":"4",
     "city":"Bevery Hills",
     "state":"CA",
     "zip":"90210",
     "price":"319250"},
    {"h_id":"6",
     "city":"Dallas",
     "state":"TX",
     "zip":"75000",
     "price":"556699"},
    {"h_id":"5",
     "city":"New York",
     "state":"NY",
     "zip":"00010",
     "price":"962500"}
    ];

_.orderBy(homes, ['city', 'state', 'zip'], ['asc', 'desc', 'asc']);

Я не видел, чтобы этот конкретный подход предлагал, так что вот краткий метод сравнения, который мне нравится использовать, который работает для обоих string а также number:

const objs = [ 
  { first_nom: 'Lazslo', last_nom: 'Jamf'     },
  { first_nom: 'Pig',    last_nom: 'Bodine'   },
  { first_nom: 'Pirate', last_nom: 'Prentice' }
];

const sortBy = fn => (a, b) => -(fn(a) < fn(b)) || +(fn(a) > fn(b))
const getLastName = o => o.last_nom
const sortByLastName = sortBy(getLastName)

objs.sort(sortByLastName)
console.log(objs.map(getLastName))

Вот объяснение sortBy():

sortBy() принимает fn который выбирает какое значение из объекта для использования в качестве сравнения и возвращает функцию, которую можно передать непосредственно Array.prototype.sort(), В этом примере мы используем o.last_nom в качестве значения для сравнения, поэтому всякий раз, когда мы получаем два объекта через Array.prototype.sort() такие как

{ first_nom: 'Lazslo', last_nom: 'Jamf' }

а также

{ first_nom: 'Pig', last_nom: 'Bodine' }

мы используем

(a, b) => -(fn(a) < fn(b)) || +(fn(a) > fn(b))

сравнить их.

Вспоминая это fn = o => o.last_nom мы можем расширить функцию сравнения до эквивалентной

(a, b) => -(a.last_nom < b.last_nom) || +(a.last_nom > b.last_nom)

Логическое ИЛИ || Оператор имеет функцию короткого замыкания, которая очень полезна здесь. Из-за того, как это работает, тело функции выше означает

if (a.last_nom < b.last_nom) return -1
return +(a.last_nom > b.last_nom)

Так что если a < b мы возвращаемся -1 иначе если a > b тогда мы вернемся +1, но если a == b, затем a < b а также a > b ложны, поэтому он возвращает +0,

В качестве дополнительного бонуса, вот эквивалент в ECMAScript 5.1 без функций стрелок, что, к сожалению, не так кратко:

var objs = [ 
  { first_nom: 'Lazslo', last_nom: 'Jamf'     },
  { first_nom: 'Pig',    last_nom: 'Bodine'   },
  { first_nom: 'Pirate', last_nom: 'Prentice' }
];

var sortBy = function (fn) {
  return function (a, b) {
    return -(fn(a) < fn(b)) || +(fn(a) > fn(b))
  }
}

var getLastName = function (o) { return o.last_nom }
var sortByLastName = sortBy(getLastName)

objs.sort(sortByLastName)
console.log(objs.map(getLastName))

Вместо использования пользовательской функции сравнения вы также можете создать тип объекта с пользовательским toString() Метод (который вызывается функцией сравнения по умолчанию):

function Person(firstName, lastName) {
    this.firtName = firstName;
    this.lastName = lastName;
}

Person.prototype.toString = function() {
    return this.lastName + ', ' + this.firstName;
}

var persons = [ new Person('Lazslo', 'Jamf'), ...]
persons.sort();

Здесь есть много хороших ответов, но я хотел бы отметить, что они могут быть расширены очень просто для достижения гораздо более сложной сортировки. Единственное, что вам нужно сделать, это использовать оператор OR для цепочки функций сравнения:

objs.sort((a,b)=> fn1(a,b) || fn2(a,b) || fn3(a,b) )

куда fn1, fn2,... - это функции сортировки, которые возвращают [-1,0,1]. Это приводит к "сортировке по fn1", "сортировке по fn2", которая в значительной степени равна ORDER BY в SQL.

Это решение основано на поведении || оператор, который оценивает первое вычисленное выражение, которое может быть преобразовано в true.

Самая простая форма имеет только одну встроенную функцию, например:

// ORDER BY last_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) )

Имея два шага с last_nom,first_nom порядок сортировки будет выглядеть так:

// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) || 
                  a.first_nom.localeCompare(b.first_nom)  )

Универсальная функция сравнения может выглядеть примерно так:

// ORDER BY <n>
let cmp = (a,b,n)=>a[n].localeCompare(b[n])

Эта функция может быть расширена для поддержки числовых полей, чувствительности к регистру, произвольных типов данных и т. Д.

Вы можете использовать их в цепочке по приоритету сортировки:

// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> cmp(a,b, "last_nom") || cmp(a,b, "first_nom") )
// ORDER_BY last_nom, first_nom DESC
objs.sort((a,b)=> cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )
// ORDER_BY last_nom DESC, first_nom DESC
objs.sort((a,b)=> -cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )

Дело в том, что чистый JavaScript с функциональным подходом может пройти долгий путь без внешних библиотек или сложного кода. Это также очень эффективно, так как не нужно разбирать строки

Попробуй это,

UPTO ES5

//Ascending Sort
items.sort(function (a, b) {
   return a.value - b.value;
});


//Descending Sort
items.sort(function (a, b) {
   return b.value - a.value;
});


IN ES6 & above:

// Ascending sort
items.sort((a, b) => a.value - b.value);

// Descending Sort
 items.sort((a, b) => b.value - a.value);

Метод sort можно изменить для сортировки чего угодно, например массива чисел, строк и даже объектов, используя функцию сравнения.

Функция сравнения передается как необязательный аргумент методу сортировки.

Функция сравнения принимает 2 аргумента, которые обычно называются a и b. На основе этих двух аргументов вы можете изменить метод сортировки, чтобы он работал так, как хотите. если:

  1. Если функция сравнения возвращает меньше 0, тогда метод sort () сортирует a с индексом ниже, чем b. Просто a будет перед b.
  2. Если функция сравнения возвращает значение 0, то метод sort () оставляет позиции элементов как есть.
  3. Если функция сравнения возвращает больше 0, тогда метод sort () сортирует a по индексу, большему, чем b. Просто a будет после b.

Ссылка: Общие сведения о сортировочном массиве чисел, строк и объектов

Использование выше концепции для применения на вашем объекте , где будет вам свойство объекта.

Пример использования:

objs.sort(sortBy('last_nom'));

Автор сценария:

/**
 * @description 
 * Returns a function which will sort an
 * array of objects by the given key.
 * 
 * @param  {String}  key
 * @param  {Boolean} reverse
 * @return {Function}     
 */
function sortBy(key, reverse) {

  // Move smaller items towards the front
  // or back of the array depending on if
  // we want to sort the array in reverse
  // order or not.
  var moveSmaller = reverse ? 1 : -1;

  // Move larger items towards the front
  // or back of the array depending on if
  // we want to sort the array in reverse
  // order or not.
  var moveLarger = reverse ? -1 : 1;

  /**
   * @param  {*} a
   * @param  {*} b
   * @return {Number}
   */
  return function(a, b) {
    if (a[key] < b[key]) {
      return moveSmaller;
    }
    if (a[key] > b[key]) {
      return moveLarger;
    }
    return 0;
  };

}

Почему бы тебе не написать короткий код?

      objs.sort((a, b) => a.last_nom > b.last_nom && 1 || -1)

Я знаю, что этот вопрос слишком старый, но я не видел ни одной реализации, похожей на мою.
Эта версия основана на идиоме преобразования Шварца.

function sortByAttribute(array, ...attrs) {
  // generate an array of predicate-objects contains
  // property getter, and descending indicator
  let predicates = attrs.map(pred => {
    let descending = pred.charAt(0) === '-' ? -1 : 1;
    pred = pred.replace(/^-/, '');
    return {
      getter: o => o[pred],
      descend: descending
    };
  });
  // schwartzian transform idiom implementation. aka: "decorate-sort-undecorate"
  return array.map(item => {
    return {
      src: item,
      compareValues: predicates.map(predicate => predicate.getter(item))
    };
  })
  .sort((o1, o2) => {
    let i = -1, result = 0;
    while (++i < predicates.length) {
      if (o1.compareValues[i] < o2.compareValues[i]) result = -1;
      if (o1.compareValues[i] > o2.compareValues[i]) result = 1;
      if (result *= predicates[i].descend) break;
    }
    return result;
  })
  .map(item => item.src);
}

Вот пример, как его использовать:

let games = [
  { name: 'Pako',              rating: 4.21 },
  { name: 'Hill Climb Racing', rating: 3.88 },
  { name: 'Angry Birds Space', rating: 3.88 },
  { name: 'Badland',           rating: 4.33 }
];

// sort by one attribute
console.log(sortByAttribute(games, 'name'));
// sort by mupltiple attributes
console.log(sortByAttribute(games, '-rating', 'name'));

Сортировка (более) сложных массивов объектов

Поскольку вы, вероятно, сталкиваетесь с более сложными структурами данных, такими как этот массив, я бы расширил решение.

TL; DR

Более подключаемая версия, основанная на очень милом ответе Ege Özcan.

проблема

Я столкнулся с ниже и не мог изменить это. Я также не хотел временно сплющивать объект. Также я не хотел использовать подчеркивание / lodash, в основном из соображений производительности и удовольствия, чтобы реализовать это самостоятельно.

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

Цель

Цель состоит в том, чтобы отсортировать его в первую очередь по People.Name.name и во вторую очередь People.Name.surname

Препятствия

Теперь в базовом решении используются скобочные обозначения для вычисления свойств для динамической сортировки. Здесь, однако, мы должны были бы также динамически создавать обозначение в скобках, так как вы ожидаете, что People['Name.name'] будет работать - что не так.

Просто делаю People['Name']['name'], с другой стороны, является статичным и позволяет только спуститься на n-й уровень.

Решение

Основным дополнением здесь будет прогулка по дереву объектов и определение значения последнего листа, который вы должны указать, а также любого промежуточного листа.

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

People.sort(dynamicMultiSort(['Name','name'], ['Name', '-surname']));
// Results in...
// [ { Name: { name: 'AAA', surname: 'ZZZ' }, Middlename: 'Abrams' },
//   { Name: { name: 'Name', surname: 'Surname' }, Middlename: 'JJ' },
//   { Name: { name: 'Name', surname: 'AAA' }, Middlename: 'Wars' } ]

// same logic as above, but strong deviation for dynamic properties 
function dynamicSort(properties) {
  var sortOrder = 1;
  // determine sort order by checking sign of last element of array
  if(properties[properties.length - 1][0] === "-") {
    sortOrder = -1;
    // Chop off sign
    properties[properties.length - 1] = properties[properties.length - 1].substr(1);
  }
  return function (a,b) {
    propertyOfA = recurseObjProp(a, properties)
    propertyOfB = recurseObjProp(b, properties)
    var result = (propertyOfA < propertyOfB) ? -1 : (propertyOfA > propertyOfB) ? 1 : 0;
    return result * sortOrder;
  };
}

/**
 * Takes an object and recurses down the tree to a target leaf and returns it value
 * @param  {Object} root - Object to be traversed.
 * @param  {Array} leafs - Array of downwards traversal. To access the value: {parent:{ child: 'value'}} -> ['parent','child']
 * @param  {Number} index - Must not be set, since it is implicit.
 * @return {String|Number}       The property, which is to be compared by sort.
 */
function recurseObjProp(root, leafs, index) {
  index ? index : index = 0
  var upper = root
  // walk down one level
  lower = upper[leafs[index]]
  // Check if last leaf has been hit by having gone one step too far.
  // If so, return result from last step.
  if (!lower) {
    return upper
  }
  // Else: recurse!
  index++
  // HINT: Bug was here, for not explicitly returning function
  // https://stackru.com/a/17528613/3580261
  return recurseObjProp(lower, leafs, index)
}

/**
 * Multi-sort your array by a set of properties
 * @param {...Array} Arrays to access values in the form of: {parent:{ child: 'value'}} -> ['parent','child']
 * @return {Number} Number - number for sort algorithm
 */
function dynamicMultiSort() {
  var args = Array.prototype.slice.call(arguments); // slight deviation to base

  return function (a, b) {
    var i = 0, result = 0, numberOfProperties = args.length;
    // REVIEW: slightly verbose; maybe no way around because of `.sort`-'s nature
    // Consider: `.forEach()`
    while(result === 0 && i < numberOfProperties) {
      result = dynamicSort(args[i])(a, b);
      i++;
    }
    return result;
  }
}

пример

Рабочий пример на JSBin

Сортировка предметов сдля конкретного случая, когда вы хотите естественную сортировку (т.е. 1,2,10,11,111).

Поддержка браузера для Intl.Collator

Комбинируя динамическое решение Ege с идеей Vinay, вы получаете хорошее надежное решение:

Array.prototype.sortBy = function() {
    function _sortByAttr(attr) {
        var sortOrder = 1;
        if (attr[0] == "-") {
            sortOrder = -1;
            attr = attr.substr(1);
        }
        return function(a, b) {
            var result = (a[attr] < b[attr]) ? -1 : (a[attr] > b[attr]) ? 1 : 0;
            return result * sortOrder;
        }
    }
    function _getSortFunc() {
        if (arguments.length == 0) {
            throw "Zero length arguments not allowed for Array.sortBy()";
        }
        var args = arguments;
        return function(a, b) {
            for (var result = 0, i = 0; result == 0 && i < args.length; i++) {
                result = _sortByAttr(args[i])(a, b);
            }
            return result;
        }
    }
    return this.sort(_getSortFunc.apply(null, arguments));
}

Использование:

// Utility for printing objects
Array.prototype.print = function(title) {
    console.log("************************************************************************");
    console.log("**** "+title);
    console.log("************************************************************************");
    for (var i = 0; i < this.length; i++) {
        console.log("Name: "+this[i].FirstName, this[i].LastName, "Age: "+this[i].Age);
    }
}

// Setup sample data
var arrObj = [
    {FirstName: "Zach", LastName: "Emergency", Age: 35},
    {FirstName: "Nancy", LastName: "Nurse", Age: 27},
    {FirstName: "Ethel", LastName: "Emergency", Age: 42},
    {FirstName: "Nina", LastName: "Nurse", Age: 48},
    {FirstName: "Anthony", LastName: "Emergency", Age: 44},
    {FirstName: "Nina", LastName: "Nurse", Age: 32},
    {FirstName: "Ed", LastName: "Emergency", Age: 28},
    {FirstName: "Peter", LastName: "Physician", Age: 58},
    {FirstName: "Al", LastName: "Emergency", Age: 51},
    {FirstName: "Ruth", LastName: "Registration", Age: 62},
    {FirstName: "Ed", LastName: "Emergency", Age: 38},
    {FirstName: "Tammy", LastName: "Triage", Age: 29},
    {FirstName: "Alan", LastName: "Emergency", Age: 60},
    {FirstName: "Nina", LastName: "Nurse", Age: 54}
];

//Unit Tests
arrObj.sortBy("LastName").print("LastName Ascending");
arrObj.sortBy("-LastName").print("LastName Descending");
arrObj.sortBy("LastName", "FirstName", "-Age").print("LastName Ascending, FirstName Ascending, Age Descending");
arrObj.sortBy("-FirstName", "Age").print("FirstName Descending, Age Ascending");
arrObj.sortBy("-Age").print("Age Descending");

Еще один вариант:

var someArray = [...];

function generateSortFn(prop, reverse) {
    return function (a, b) {
        if (a[prop] < b[prop]) return reverse ? 1 : -1;
        if (a[prop] > b[prop]) return reverse ? -1 : 1;
        return 0;
    };
}

someArray.sort(generateSortFn('name', true));

сортирует по возрастанию по умолчанию.

Вот мой взгляд на это:

В order Параметр является необязательным и по умолчанию имеет значение "ASC" для возрастания.

function sortByProperty(array,property,order="ASC") {
  return array.sort((a,b) => order === "ASC" ?
    a[property] > b[property] ? 1 : a[property] < b[property] ? -1 : 0
  : a[property] > b[property] ? -1 : a[property] < b[property] ? 1 : 0
  );
}

СНИППЕТ

function sortByProperty(array,property,order="ASC") {
  return array.sort((a,b) => order === "ASC" ?
    a[property] > b[property] ? 1 : a[property] < b[property] ? -1 : 0
  : a[property] > b[property] ? -1 : a[property] < b[property] ? 1 : 0
  );
}

const rockStars = [
  { name: "Axl",
    lastname: "Rose" },
  { name: "Elthon",
    lastname: "John" },
  { name: "Paul",
    lastname: "McCartney" },
  { name: "Lou",
    lastname: "Reed" }
];

sortByProperty(rockStars,"name");

console.log("Ordered by name A-Z:");
rockStars.forEach((item) => console.log(item.name + " " + item.lastname));

sortByProperty(rockStars,"lastname","DESC");

console.log("\nOrdered by lastname Z-A:");
rockStars.forEach((item) => console.log(item.lastname + ", " + item.name));

Простая функция, которая сортирует массив объектов по свойству

function sortArray(array, property, direction) {
    direction = direction || 1;
    array.sort(function compare(a, b) {
        let comparison = 0;
        if (a[property] > b[property]) {
            comparison = 1 * direction;
        } else if (a[property] < b[property]) {
            comparison = -1 * direction;
        }
        return comparison;
    });
    return array; // Chainable
}

Использование:

var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];

sortArray(objs, "last_nom"); // Asc
sortArray(objs, "last_nom", -1); // Desc

Простой способ:

objs.sort(function(a,b) {
  return b.last_nom.toLowerCase() < a.last_nom.toLowerCase();
});

Видеть, что '.toLowerCase()' необходимо предотвратить ошибки при сравнении строк.

objs.sort(function(a,b){return b.last_nom>a.last_nom})

Учитывая оригинальный пример:

var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];

Сортировать по нескольким полям:

objs.sort(function(left, right) {
    var last_nom_order = left.last_nom.localeCompare(right.last_nom);
    var first_nom_order = left.first_nom.localeCompare(right.first_nom);
    return last_nom_order || first_nom_order;
});

Заметки

  • a.localeCompare(b) универсально поддерживается и возвращает -1,0,1, если a<b,a==b,a>b соответственно.
  • || в последней строке дает last_nom приоритет над first_nom,
  • Вычитание работает над числовыми полями: var age_order = left.age - right.age;
  • Отрицать в обратном порядке, return -last_nom_order || -first_nom_order || -age_order;

Дополнительные параметры desc для кода Ege Özcan

function dynamicSort(property, desc) {
    if (desc) {
        return function (a, b) {
            return (a[property] > b[property]) ? -1 : (a[property] < b[property]) ? 1 : 0;
        }   
    }
    return function (a, b) {
        return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
    }
}
Другие вопросы по тегам