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

1335

Я получил следующие объекты с использованием AJAX и сохранил их в массиве:

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": "5",
        "city": "New York",
        "state": "NY",
        "zip": "00010",
        "price": "962500"
    }
];

Как создать функцию для сортировки объектов по priceсвойству в порядке возрастания или убывания , используя только JavaScript?

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

Ответы:

1674

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

homes.sort(function(a, b) {
    return parseFloat(a.price) - parseFloat(b.price);
});

Или после версии ES6:

homes.sort((a, b) => parseFloat(a.price) - parseFloat(b.price));

Некоторая документация может быть найдена здесь .

Stobor
источник
184
Вы можете использовать string1.localeCompare(string2)для сравнения строк
Брадвидо
62
Имейте в виду, что localeCompare()регистр не учитывается . Если вы хотите, чтобы с учетом регистра, вы можете использовать (string1 > string2) - (string1 < string2). Логические значения приводятся к целым числам 0 и 1 для вычисления разницы.
Дон Киркби
2
Спасибо за обновление, @Pointy, я не помню, чтобы столкнулся с этой проблемой, но, возможно, поведение изменилось за последние пару лет. Несмотря на это, localeCompare()документация показывает, что вы можете явно указать, хотите ли вы учитывать регистр, числовую сортировку и другие параметры.
Дон Киркби
2
@ sg28 Я думаю, вы неправильно поняли объяснение MDN. Это не говорит о том, что функция сортировки ненадежна , это говорит о том, что она не стабильна . Я понимаю, почему это может сбивать с толку, но это не утверждение, что оно не подходит для использования. В контексте алгоритмов сортировки термин стабильный имеет конкретное значение - «равные» элементы в списке сортируются в том же порядке, что и во входных данных . Это совершенно не связано с идеей кода, который нестабилен (то есть еще не готов к использованию).
Стобор
1
Если вы хотите сортировать по определенным строковым значениям, например, по городам, вы можете использовать: this.homes.sort ((current, next) => {return current.city.localeCompare (next.city)});
Хорхе Вальверт
675

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

const sort_by = (field, reverse, primer) => {

  const key = primer ?
    function(x) {
      return primer(x[field])
    } :
    function(x) {
      return x[field]
    };

  reverse = !reverse ? 1 : -1;

  return function(a, b) {
    return a = key(a), b = key(b), reverse * ((a > b) - (b > a));
  }
}


//Now you can sort by any field at will...

const 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:"5",city:"New York",state:"NY",zip:"00010",price:"962500"}];

// Sort by price high to low
console.log(homes.sort(sort_by('price', true, parseInt)));

// Sort by city, case-insensitive, A-Z
console.log(homes.sort(sort_by('city', false, (a) =>  a.toUpperCase()
)));

Триптих
источник
7
nickb - вы неправильно читаете код sort_byвыполняется в O (1) и возвращает функцию, используемую встроенной сортировкой (O (N log N)) для сравнения элементов в списке. Общая сложность O (n log n) * O (1), которая сводится к O (n log n), или такой же, как быстрая сортировка.
Триптих
1
Одна проблема, с которой я столкнулся, заключается в том, что при reverse = false она будет сортировать числа как 1,2,3,4 ... но Strings как z, y, x ...
Abby
4
Небольшое улучшение:var key = primer ? function (x) { return primer(x[field]); } : function (x) { return x[field]; }
ErikE
6
Хотя [1,-1][+!!reverse]выглядит круто, это ужасно. Если пользователь не может вызвать ваш метод должным образом, накажите его, а не пытайтесь каким-то образом понять его, несмотря ни на что.
Инго Бюрк
2
Разве не было бы лучше подготовить исходные данные, это вызвало бы последовательный анализ, когда очевидно, что исходные данные требуют некоторой настройки.
Геррит Бринк
134

Чтобы отсортировать его, вам нужно создать функцию сравнения с двумя аргументами. Затем вызовите функцию сортировки с этой функцией сравнения следующим образом:

// a and b are object elements of your array
function mycomparator(a,b) {
  return parseInt(a.price, 10) - parseInt(b.price, 10);
}
homes.sort(mycomparator);

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

Рикардо Маримон
источник
3
И вот ссылка, которая фактически объясняет эту тему вместо того, чтобы сказать «это слишком сложно, вы все равно не поймете это»: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Роланд Иллиг
51

для сортировки строк, если кому-то это нужно,

const dataArr = {

  "hello": [{
    "id": 114,
    "keyword": "zzzzzz",
    "region": "Sri Lanka",
    "supportGroup": "administrators",
    "category": "Category2"
  }, {
    "id": 115,
    "keyword": "aaaaa",
    "region": "Japan",
    "supportGroup": "developers",
    "category": "Category2"
  }]

};
const sortArray = dataArr['hello'];

console.log(sortArray.sort((a, b) => {
  if (a.region < b.region)
    return -1;
  if (a.region > b.region)
    return 1;
  return 0;
}));

Ishan Liyanage
источник
38

Если у вас есть браузер, совместимый с ES6, вы можете использовать:

Разница между возрастающим и убывающим порядком сортировки является знаком значения, возвращаемого вашей функцией сравнения:

var ascending = homes.sort((a, b) => Number(a.price) - Number(b.price));
var descending = homes.sort((a, b) => Number(b.price) - Number(a.price));

Вот рабочий фрагмент кода:

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": "5",
  "city": "New York",
  "state": "NY",
  "zip": "00010",
  "price": "962500"
}];

homes.sort((a, b) => Number(a.price) - Number(b.price));
console.log("ascending", homes);

homes.sort((a, b) => Number(b.price) - Number(a.price));
console.log("descending", homes);

Стивен Куан
источник
22

Вы хотите отсортировать его в Javascript, верно? То, что вы хотите, это sort()функция . В этом случае вам нужно написать функцию сравнения и передать ее sort(), так что-то вроде этого:

function comparator(a, b) {
    return parseInt(a["price"], 10) - parseInt(b["price"], 10);
}

var json = { "homes": [ /* your previous data */ ] };
console.log(json["homes"].sort(comparator));

Ваш компаратор берет один из каждого из вложенных хешей внутри массива и решает, какой из них выше, проверяя поле «цена».

Тим Гилберт
источник
21

Я рекомендую GitHub: Array sortBy - лучшая реализация sortByметода, использующего преобразование Шварца

Но сейчас мы собираемся попробовать этот подход Gist: sortBy-old.js .
Давайте создадим метод сортировки массивов, позволяющий упорядочивать объекты по какому-либо свойству.

Создание функции сортировки

var sortBy = (function () {
  var toString = Object.prototype.toString,
      // default parser function
      parse = function (x) { return x; },
      // gets the item to be sorted
      getItem = function (x) {
        var isObject = x != null && typeof x === "object";
        var isProp = isObject && this.prop in x;
        return this.parser(isProp ? x[this.prop] : x);
      };

  /**
   * Sorts an array of elements.
   *
   * @param  {Array} array: the collection to sort
   * @param  {Object} cfg: the configuration options
   * @property {String}   cfg.prop: property name (if it is an Array of objects)
   * @property {Boolean}  cfg.desc: determines whether the sort is descending
   * @property {Function} cfg.parser: function to parse the items to expected type
   * @return {Array}
   */
  return function sortby (array, cfg) {
    if (!(array instanceof Array && array.length)) return [];
    if (toString.call(cfg) !== "[object Object]") cfg = {};
    if (typeof cfg.parser !== "function") cfg.parser = parse;
    cfg.desc = !!cfg.desc ? -1 : 1;
    return array.sort(function (a, b) {
      a = getItem.call(cfg, a);
      b = getItem.call(cfg, b);
      return cfg.desc * (a < b ? -1 : +(a > b));
    });
  };

}());

Установка несортированных данных

var data = [
  {date: "2011-11-14T16:30:43Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T17:22:59Z", quantity: 2, total: 90,  tip: 0,   type: "Tab"},
  {date: "2011-11-14T16:28:54Z", quantity: 1, total: 300, tip: 200, type: "visa"},
  {date: "2011-11-14T16:53:41Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:48:46Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T17:25:45Z", quantity: 2, total: 200, tip: 0,   type: "cash"},
  {date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa"},
  {date: "2011-11-14T16:58:03Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:20:19Z", quantity: 2, total: 190, tip: 100, type: "tab"},
  {date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab"},
  {date: "2011-11-14T17:07:21Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:54:06Z", quantity: 1, total: 100, tip: 0,   type: "Cash"}
];

Используй это

Расположите массив, "date"какString

// sort by @date (ascending)
sortBy(data, { prop: "date" });

// expected: first element
// { date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab" }

// expected: last element
// { date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa"}

Если вы хотите игнорировать регистр, установите parserобратный вызов:

// sort by @type (ascending) IGNORING case-sensitive
sortBy(data, {
    prop: "type",
    parser: (t) => t.toUpperCase()
});

// expected: first element
// { date: "2011-11-14T16:54:06Z", quantity: 1, total: 100, tip: 0, type: "Cash" }

// expected: last element
// { date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa" }

Если вы хотите преобразовать "date"поле как Dateтип:

// sort by @date (descending) AS Date object
sortBy(data, {
    prop: "date",
    desc: true,
    parser: (d) => new Date(d)
});

// expected: first element
// { date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa"}

// expected: last element
// { date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab" }

Здесь вы можете поиграть с кодом: jsbin.com/lesebi

Благодаря @Ozesh по его отзывам, проблема, связанная со свойствами с ложными значениями, была исправлена.

jherax
источник
Это, кажется, ломается, когда поле является нулевым.
ЦНев
В случае, когда вы сортируете числа и встречаете «0» между массивом объектов, вы можете заметить, что вышеприведенный код ломается. Вот быстрое исправление: var checkNaN = function (value) { return Number.isNaN(Number(value)) ? 0 : value; } за ним следует: return function (array, o) { .... a = _getItem.call (o, a); a = checkNaN (a); b = _getItem.call (o, b); b = checkNaN (b); return o.desc * (a <b? -1: + (a> b)); });
Озеш
18

Используйте lodash.sortBy (инструкции, использующие commonjs, вы также можете просто поместить скрипт include-тега для cdn вверху вашего html)

var sortBy = require('lodash.sortby');
// or
sortBy = require('lodash').sortBy;

В порядке убывания

var descendingOrder = sortBy( homes, 'price' ).reverse();

По возрастанию

var ascendingOrder = sortBy( homes, 'price' );
Эван Кэрролл
источник
1
Илиconst sortBy = require('lodash/sortBy'); let calendars = sortBy(calendarListResponse.items, cal => cal.summary);
mpen
не уверен, изменился ли loadash недавно к его названию OrderByimport { orderBy } from 'lodash'; ... ... return orderBy ( rows, 'fieldName' ).reverse();
montelof
8

Этого можно было бы достичь с помощью простой однострочной функции сортировки valueof () . Запустите фрагмент кода ниже, чтобы увидеть демо.

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": "5",
        "city": "New York",
        "state": "NY",
        "zip": "00010",
        "price": "962500"
    }
];

console.log("To sort descending/highest first, use operator '<'");

homes.sort(function(a,b) { return a.price.valueOf() < b.price.valueOf();});

console.log(homes);

console.log("To sort ascending/lowest first, use operator '>'");

homes.sort(function(a,b) { return a.price.valueOf() > b.price.valueOf();});

console.log(homes);

Аджай Сингх
источник
8

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

function getSortedData(data, prop, isAsc) {
    return data.sort((a, b) => {
        return (a[prop] < b[prop] ? -1 : 1) * (isAsc ? 1 : -1)
    });
}
Сантош
источник
6

Хотя я знаю, что ОП хотел отсортировать массив чисел, этот вопрос был помечен как ответ на аналогичные вопросы, касающиеся строк. Для этого факта, приведенные выше ответы не рассматривают сортировку массива текста, где регистр важен. Большинство ответов принимают строковые значения и преобразуют их в верхний / нижний регистр, а затем сортируют так или иначе. Требования, которых я придерживаюсь, просты:

  • Сортировать по алфавиту AZ
  • Прописные значения одного и того же слова должны стоять перед строчными
  • Значения одной буквы (A / A, B / B) должны быть сгруппированы вместе

Я ожидаю, [ A, a, B, b, C, c ]но ответы выше возвращаются A, B, C, a, b, c. Я на самом деле почесал голову над этим дольше, чем хотел (вот почему я публикую это в надежде, что это поможет по крайней мере еще одному человеку). В то время как два пользователя упоминают localeCompareфункцию в комментариях для помеченного ответа, я не видел ее до тех пор, пока не наткнулся на функцию во время поиска. После прочтения документации String.prototype.localeCompare () я смог придумать следующее:

var values = [ "Delta", "charlie", "delta", "Charlie", "Bravo", "alpha", "Alpha", "bravo" ];
var sorted = values.sort((a, b) => a.localeCompare(b, undefined, { caseFirst: "upper" }));
// Result: [ "Alpha", "alpha", "Bravo", "bravo", "Charlie", "charlie", "Delta", "delta" ]

Это говорит функции сортировать заглавные значения перед строчными. Вторым параметром в localeCompareфункции является определение языка, но если вы оставите его, undefinedон автоматически определит язык для вас.

Это работает так же и для сортировки массива объектов:

var values = [
    { id: 6, title: "Delta" },
    { id: 2, title: "charlie" },
    { id: 3, title: "delta" },
    { id: 1, title: "Charlie" },
    { id: 8, title: "Bravo" },
    { id: 5, title: "alpha" },
    { id: 4, title: "Alpha" },
    { id: 7, title: "bravo" }
];
var sorted = values
    .sort((a, b) => a.title.localeCompare(b.title, undefined, { caseFirst: "upper" }));
Митчелл Скурник
источник
5

Вы можете использовать sortметод JavaScript с функцией обратного вызова:

function compareASC(homeA, homeB)
{
    return parseFloat(homeA.price) - parseFloat(homeB.price);
}

function compareDESC(homeA, homeB)
{
    return parseFloat(homeB.price) - parseFloat(homeA.price);
}

// Sort ASC
homes.sort(compareASC);

// Sort DESC
homes.sort(compareDESC);
Джон Г
источник
4

Вот кульминация всех ответов выше.

Проверка скрипки: http://jsfiddle.net/bobberino/4qqk3/

var sortOn = function (arr, prop, reverse, numeric) {

    // Ensure there's a property
    if (!prop || !arr) {
        return arr
    }

    // Set up sort function
    var sort_by = function (field, rev, primer) {

        // Return the required a,b function
        return function (a, b) {

            // Reset a, b to the field
            a = primer(a[field]), b = primer(b[field]);

            // Do actual sorting, reverse as needed
            return ((a < b) ? -1 : ((a > b) ? 1 : 0)) * (rev ? -1 : 1);
        }

    }

    // Distinguish between numeric and string to prevent 100's from coming before smaller
    // e.g.
    // 1
    // 20
    // 3
    // 4000
    // 50

    if (numeric) {

        // Do sort "in place" with sort_by function
        arr.sort(sort_by(prop, reverse, function (a) {

            // - Force value to a string.
            // - Replace any non numeric characters.
            // - Parse as float to allow 0.02 values.
            return parseFloat(String(a).replace(/[^0-9.-]+/g, ''));

        }));
    } else {

        // Do sort "in place" with sort_by function
        arr.sort(sort_by(prop, reverse, function (a) {

            // - Force value to string.
            return String(a).toUpperCase();

        }));
    }


}
боб
источник
Можете ли вы объяснить, что значит иметь * (Откр. -1: 1);
TechTurtle
Это должно изменить порядок (восходящий или нисходящий), часть rev просто переворачивает нормальные результаты, когда аргумент rev равен true. В противном случае он просто умножится на 1, что ничего не делает, при установке он умножит результат на -1, тем самым инвертировав результат.
Боб
3

Для сортировки массива вы должны определить функцию сравнения. Эта функция всегда будет отличаться в зависимости от желаемого шаблона или порядка сортировки (т. Е. По возрастанию или по убыванию).

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

function sorterAscending(a,b) {
    return a-b;
}

function sorterDescending(a,b) {
    return b-a;
}

function sorterPriceAsc(a,b) {
    return parseInt(a['price']) - parseInt(b['price']);
}

function sorterPriceDes(a,b) {
    return parseInt(b['price']) - parseInt(b['price']);
}

Сортировка чисел (по алфавиту и по возрастанию):

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();

Сортировка чисел (по алфавиту и по убыванию):

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();
fruits.reverse();

Сортировка чисел (по возрастанию):

var points = [40,100,1,5,25,10];
points.sort(sorterAscending());

Сортировка чисел (по номерам и по убыванию):

var points = [40,100,1,5,25,10];
points.sort(sorterDescending());

Как и выше, используйте методы sorterPriceAsc и sorterPriceDes для вашего массива с нужным ключом.

homes.sort(sorterPriceAsc()) or homes.sort(sorterPriceDes())
Лалит Кумар Маурья
источник
3

Я также работал с некоторой оценкой и сортировкой нескольких полей:

arr = [
    {type:'C', note:834},
    {type:'D', note:732},
    {type:'D', note:008},
    {type:'F', note:474},
    {type:'P', note:283},
    {type:'P', note:165},
    {type:'X', note:173},
    {type:'Z', note:239},
];

arr.sort(function(a,b){        
    var _a = ((a.type==='C')?'0':(a.type==='P')?'1':'2');
    _a += (a.type.localeCompare(b.type)===-1)?'0':'1';
    _a += (a.note>b.note)?'1':'0';
    var _b = ((b.type==='C')?'0':(b.type==='P')?'1':'2');
    _b += (b.type.localeCompare(a.type)===-1)?'0':'1';
    _b += (b.note>a.note)?'1':'0';
    return parseInt(_a) - parseInt(_b);
});

Результат

[
    {"type":"C","note":834},
    {"type":"P","note":165},
    {"type":"P","note":283},
    {"type":"D","note":8},
    {"type":"D","note":732},
    {"type":"F","note":474},
    {"type":"X","note":173},
    {"type":"Z","note":239}
]
Родольфо Хорхе Немер Ногейра
источник
3

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

(function(){
    var keyPaths = [];

    var saveKeyPath = function(path) {
        keyPaths.push({
            sign: (path[0] === '+' || path[0] === '-')? parseInt(path.shift()+1) : 1,
            path: path
        });
    };

    var valueOf = function(object, path) {
        var ptr = object;
        for (var i=0,l=path.length; i<l; i++) ptr = ptr[path[i]];
        return ptr;
    };

    var comparer = function(a, b) {
        for (var i = 0, l = keyPaths.length; i < l; i++) {
            aVal = valueOf(a, keyPaths[i].path);
            bVal = valueOf(b, keyPaths[i].path);
            if (aVal > bVal) return keyPaths[i].sign;
            if (aVal < bVal) return -keyPaths[i].sign;
        }
        return 0;
    };

    Array.prototype.sortBy = function() {
        keyPaths = [];
        for (var i=0,l=arguments.length; i<l; i++) {
            switch (typeof(arguments[i])) {
                case "object": saveKeyPath(arguments[i]); break;
                case "string": saveKeyPath(arguments[i].match(/[+-]|[^.]+/g)); break;
            }
        }
        return this.sort(comparer);
    };    
})();

Применение:

var data = [
    { name: { first: 'Josh', last: 'Jones' }, age: 30 },
    { name: { first: 'Carlos', last: 'Jacques' }, age: 19 },
    { name: { first: 'Carlos', last: 'Dante' }, age: 23 },
    { name: { first: 'Tim', last: 'Marley' }, age: 9 },
    { name: { first: 'Courtney', last: 'Smith' }, age: 27 },
    { name: { first: 'Bob', last: 'Smith' }, age: 30 }
]

data.sortBy('age'); // "Tim Marley(9)", "Carlos Jacques(19)", "Carlos Dante(23)", "Courtney Smith(27)", "Josh Jones(30)", "Bob Smith(30)"

Сортировка по вложенным свойствам с точечным синтаксисом или массивом:

data.sortBy('name.first'); // "Bob Smith(30)", "Carlos Dante(23)", "Carlos Jacques(19)", "Courtney Smith(27)", "Josh Jones(30)", "Tim Marley(9)"
data.sortBy(['name', 'first']); // "Bob Smith(30)", "Carlos Dante(23)", "Carlos Jacques(19)", "Courtney Smith(27)", "Josh Jones(30)", "Tim Marley(9)"

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

data.sortBy('name.first', 'age'); // "Bob Smith(30)", "Carlos Jacques(19)", "Carlos Dante(23)", "Courtney Smith(27)", "Josh Jones(30)", "Tim Marley(9)"
data.sortBy('name.first', '-age'); // "Bob Smith(30)", "Carlos Dante(23)", "Carlos Jacques(19)", "Courtney Smith(27)", "Josh Jones(30)", "Tim Marley(9)"

Вы можете раскошелиться на репо: https://github.com/eneko/Array.sortBy

Энеко Алонсо
источник
Мне очень нравится этот ответ из-за sortByлаконичного синтаксиса. Простой в использовании - даже с вложенными полями - при сохранении отличной читаемости кода. Спасибо!
Манфред Урбан
3

С помощью ECMAScript 6 ответ StoBor можно сделать еще более кратким:

homes.sort((a, b) => a.price - b.price)
CracyD
источник
3

По убыванию цены:

homes.sort((x,y) => {return y.price - x.price})

В порядке возрастания цены:

homes.sort((x,y) => {return x.price - y.price})
оборота Аруши Байпай
источник
2

Если вы используете Underscore.js , попробуйте sortBy:

// price is of an integer type
_.sortBy(homes, "price"); 

// price is of a string type
_.sortBy(homes, function(home) {return parseInt(home.price);}); 
Виталий Федоренко
источник
2

Вот слегка измененная версия элегантной реализации из книги «JavaScript: хорошие части».

Примечание : Эта версия byİŞ стабильной . Он сохраняет порядок первой сортировки при выполнении следующей цепочки сортировки.

Я добавил isAscendingпараметр к нему. Также преобразовал это вES6 стандарты и "более новые" хорошие части как рекомендовано автором.

Вы можете сортировать по возрастанию, а также по убыванию и сортировать по цепочке по нескольким свойствам.

const by = function (name, minor, isAscending=true) {
    const reverseMutliplier = isAscending ? 1 : -1;
    return function (o, p) {
        let a, b;
        let result;
        if (o && p && typeof o === "object" && typeof p === "object") {
            a = o[name];
            b = p[name];
            if (a === b) {
                return typeof minor === 'function' ? minor(o, p) : 0;
            }
            if (typeof a === typeof b) {
                result = a < b ? -1 : 1;
            } else {
                result = typeof a < typeof b ? -1 : 1;
            }
            return result * reverseMutliplier;
        } else {
            throw {
                name: "Error",
                message: "Expected an object when sorting by " + name
            };
        }
    };
};

let s = [
    {first: 'Joe',   last: 'Besser'},
    {first: 'Moe',   last: 'Howard'},
    {first: 'Joe',   last: 'DeRita'},
    {first: 'Shemp', last: 'Howard'},
    {first: 'Larry', last: 'Fine'},
    {first: 'Curly', last: 'Howard'}
];

// Sort by: first ascending, last ascending
s.sort(by("first", by("last")));    
console.log("Sort by: first ascending, last ascending: ", s);     // "[
//     {"first":"Curly","last":"Howard"},
//     {"first":"Joe","last":"Besser"},     <======
//     {"first":"Joe","last":"DeRita"},     <======
//     {"first":"Larry","last":"Fine"},
//     {"first":"Moe","last":"Howard"},
//     {"first":"Shemp","last":"Howard"}
// ]

// Sort by: first ascending, last descending
s.sort(by("first", by("last", 0, false)));  
console.log("sort by: first ascending, last descending: ", s);    // "[
//     {"first":"Curly","last":"Howard"},
//     {"first":"Joe","last":"DeRita"},     <========
//     {"first":"Joe","last":"Besser"},     <========
//     {"first":"Larry","last":"Fine"},
//     {"first":"Moe","last":"Howard"},
//     {"first":"Shemp","last":"Howard"}
// ]

mythicalcoder
источник
мы могли бы отсортировать {"first":"Curly","last":"Howard", "property" : {"id" : "1"}}тип массива по идентификатору?
Саху V Кумар
да, функция должна быть слегка изменена, чтобы принять новый параметр, скажем, nestedName. Затем вы звоните byс name = "property", nestedName = "id"
mythicalcoder
2

Только для обычного массива значений элементов:

function sortArrayOfElements(arrayToSort) {
    function compareElements(a, b) {
        if (a < b)
            return -1;
        if (a > b)
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareElements);
}

e.g. 1:
var array1 = [1,2,545,676,64,2,24]
output : [1, 2, 2, 24, 64, 545, 676]

var array2 = ["v","a",545,676,64,2,"24"]
output: ["a", "v", 2, "24", 64, 545, 676]

Для массива объектов:

function sortArrayOfObjects(arrayToSort, key) {
    function compareObjects(a, b) {
        if (a[key] < b[key])
            return -1;
        if (a[key] > b[key])
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareObjects);
}

e.g. 1: var array1= [{"name": "User4", "value": 4},{"name": "User3", "value": 3},{"name": "User2", "value": 2}]

output : [{"name": "User2", "value": 2},{"name": "User3", "value": 3},{"name": "User4", "value": 4}]
Umesh
источник
2

Создайте функцию и выполните сортировку на основе ввода, используя приведенный ниже код

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": "5",
    "city": "New York",
    "state": "NY",
    "zip": "00010",
    "price": "962500"

 }];

 function sortList(list,order){
     if(order=="ASC"){
        return list.sort((a,b)=>{
            return parseFloat(a.price) - parseFloat(b.price);
        })
     }
     else{
        return list.sort((a,b)=>{
            return parseFloat(b.price) - parseFloat(a.price);
        });
     }
 }

 sortList(homes,'DESC');
 console.log(homes);
Эндрю Райан
источник
2

Вы можете использовать string1.localeCompare (string2) для сравнения строк

this.myArray.sort((a,b) => { 
    return a.stringProp.localeCompare(b.stringProp);
});

Обратите внимание , что localCompareв случае в чувствительной

оборота брадвидо
источник
1

Для сортировки по нескольким объектам поля. Введите имя вашего поля в arrpropмассив, как ["a","b","c"] затем введите второй параметр arrsourceфактического источника, который мы хотим отсортировать.

function SortArrayobject(arrprop,arrsource){
arrprop.forEach(function(i){
arrsource.sort(function(a,b){
return ((a[i] < b[i]) ? -1 : ((a[i] > b[i]) ? 1 : 0));
});
});
return arrsource;
}
Прадип Талавия
источник
1

Вам понадобятся две функции

function desc(a, b) {
 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
}

function asc(a, b) {
  return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}

Затем вы можете применить это к любому свойству объекта:

 data.sort((a, b) => desc(parseFloat(a.price), parseFloat(b.price)));

let data = [
    {label: "one", value:10},
    {label: "two", value:5},
    {label: "three", value:1},
];

// sort functions
function desc(a, b) {
 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
}

function asc(a, b) {
 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}

// DESC
data.sort((a, b) => desc(a.value, b.value));

document.body.insertAdjacentHTML(
 'beforeend', 
 '<strong>DESCending sorted</strong><pre>' + JSON.stringify(data) +'</pre>'
);

// ASC
data.sort((a, b) => asc(a.value, b.value));

document.body.insertAdjacentHTML(
 'beforeend', 
 '<strong>ASCending sorted</strong><pre>' + JSON.stringify(data) +'</pre>'
);

OzzyCzech
источник
0

Недавно я написал универсальную функцию для управления этим для вас, если вы хотите использовать его.

/**
 * Sorts an object into an order
 *
 * @require jQuery
 *
 * @param object Our JSON object to sort
 * @param type Only alphabetical at the moment
 * @param identifier The array or object key to sort by
 * @param order Ascending or Descending
 *
 * @returns Array
 */
function sortItems(object, type, identifier, order){

    var returnedArray = [];
    var emptiesArray = []; // An array for all of our empty cans

    // Convert the given object to an array
    $.each(object, function(key, object){

        // Store all of our empty cans in their own array
        // Store all other objects in our returned array
        object[identifier] == null ? emptiesArray.push(object) : returnedArray.push(object);

    });

    // Sort the array based on the type given
    switch(type){

        case 'alphabetical':

            returnedArray.sort(function(a, b){

                return(a[identifier] == b[identifier]) ? 0 : (

                    // Sort ascending or descending based on order given
                    order == 'asc' ? a[identifier] > b[identifier] : a[identifier] < b[identifier]

                ) ? 1 : -1;

            });

            break;

        default:

    }

    // Return our sorted array along with the empties at the bottom depending on sort order
    return order == 'asc' ? returnedArray.concat(emptiesArray) : emptiesArray.concat(returnedArray);

}
Брэд Берд
источник
0
homes.sort(function(a, b){
  var nameA=a.prices.toLowerCase(), nameB=b.prices.toLowerCase()
  if (nameA < nameB) //sort string ascending
    return -1 
  if (nameA > nameB)
    return 1
  return 0 //default return value (no sorting)
})
user3346960
источник
0

Привет, прочитав эту статью, я создал sortComparator для своих нужд, с возможностью сравнивать более одного атрибута json, и я хочу поделиться им с вами.

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

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": "5",
    "city": "New York",
    "state": "NY",
    "zip": "00010",
    "price": "962500"

}];

// comp = array of attributes to sort
// comp = ['attr1', 'attr2', 'attr3', ...]
function sortComparator(a, b, comp) {
    // Compare the values of the first attribute
    if (a[comp[0]] === b[comp[0]]) {
        // if EQ proceed with the next attributes
        if (comp.length > 1) {
            return sortComparator(a, b, comp.slice(1));
        } else {
            // if no more attributes then return EQ
            return 0;
        }
    } else {
        // return less or great
        return (a[comp[0]] < b[comp[0]] ? -1 : 1)
    }
}

// Sort array homes
homes.sort(function(a, b) {
    return sortComparator(a, b, ['state', 'city', 'zip']);
});

// display the array
homes.forEach(function(home) {
    console.log(home.h_id, home.city, home.state, home.zip, home.price);
});

и результат

$ node sort
4 Bevery Hills CA 90210 319250
5 New York NY 00010 962500
3 Dallas TX 75201 162500

и другой вид

homes.sort(function(a, b) {
    return sortComparator(a, b, ['city', 'zip']);
});

с результатом

$ node sort
4 Bevery Hills CA 90210 319250
3 Dallas TX 75201 162500
5 New York NY 00010 962500
Джордж Вриниос
источник
0

Простой код:

    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": "5",
            "city": "New York",
            "state": "NY",
            "zip": "00010",
            "price": "962500"
        }
    ];

    let sortByPrice = homes.sort(function (a, b) 
    {
      return parseFloat(b.price) - parseFloat(a.price);
    });

    for (var i=0; i<sortByPrice.length; i++)
    {
      document.write(sortByPrice[i].h_id+' '+sortByPrice[i].city+' '
       +sortByPrice[i].state+' '
       +sortByPrice[i].zip+' '+sortByPrice[i].price);
      document.write("<br>");
    }

rashedcs
источник
0
 function compareValues(key, order = 'asc') {
  return function innerSort(a, b) {
    if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) {
      // property doesn't exist on either object
      return 0;
    }

    const varA = (typeof a[key] === 'string')
      ? a[key].toUpperCase() : a[key];
    const varB = (typeof b[key] === 'string')
      ? b[key].toUpperCase() : b[key];

    let comparison = 0;
    if (varA > varB) {
      comparison = 1;
    } else if (varA < varB) {
      comparison = -1;
    }
    return (
      (order === 'desc') ? (comparison * -1) : comparison
    );
  };
}

http://yazilimsozluk.com/sort-array-in-javascript-by-asc-or-desc

user1688401
источник