Сортировать объект JavaScript по ключу - PullRequest
409 голосов
/ 29 марта 2011

Мне нужно отсортировать объекты JavaScript по ключу.

Отсюда следующее:

{ 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' }

станет:

{ 'a' : 'dsfdsfsdf', 'b' : 'asdsad', 'c' : 'masdas' }

Ответы [ 28 ]

362 голосов
/ 28 июня 2015

Другие ответы на этот вопрос устарели, никогда не соответствовали реальности реализации, и теперь официально становятся неверными после публикации спецификации ES6 / ES2015.


См. раздел порядок итераций свойства in Исследование ES6 Акселем Раушмайером :

Все методы, которые выполняют итерации по ключам свойств, делают это вв том же порядке:

  1. Сначала все индексы Array, отсортированные по номерам.
  2. Затем все строковые ключи (не являющиеся индексами), в том порядке, в котором они были созданы.
  3. Затем все символы в том порядке, в котором они были созданы.

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

Вот как вы можете отсортировать объект по его ключам / свойствам в алфавитном порядке:

const unordered = {
  'b': 'foo',
  'c': 'bar',
  'a': 'baz'
};

console.log(JSON.stringify(unordered));
// → '{"b":"foo","c":"bar","a":"baz"}'

const ordered = {};
Object.keys(unordered).sort().forEach(function(key) {
  ordered[key] = unordered[key];
});

console.log(JSON.stringify(ordered));
// → '{"a":"baz","b":"foo","c":"bar"}'

Используйте var вместо const для совместимости с двигателями ES5.

231 голосов
/ 29 марта 2011

JavaScript объекты 1 не упорядочены. Бессмысленно пытаться «сортировать» их. Если вы хотите перебрать свойства объекта, вы можете отсортировать ключи и затем извлечь связанные значения:

var myObj = {
    'b': 'asdsadfd',
    'c': 'masdasaf',
    'a': 'dsfdsfsdf'
  },
  keys = [],
  k, i, len;

for (k in myObj) {
  if (myObj.hasOwnProperty(k)) {
    keys.push(k);
  }
}

keys.sort();

len = keys.length;

for (i = 0; i < len; i++) {
  k = keys[i];
  console.log(k + ':' + myObj[k]);
}

Альтернативная реализация с использованием Object.keys фантазия:

var myObj = {
    'b': 'asdsadfd',
    'c': 'masdasaf',
    'a': 'dsfdsfsdf'
  },
  keys = Object.keys(myObj),
  i, len = keys.length;

keys.sort();

for (i = 0; i < len; i++) {
  k = keys[i];
  console.log(k + ':' + myObj[k]);
}

1 Не для педантизма, но нет такой вещи как объект JSON .

140 голосов
/ 14 апреля 2015

Многие люди упоминают, что "объекты не могут быть отсортированы" , но после этого они дают вам решение, которое работает. Парадокс, не правда ли?

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

И я думаю, что мы могли бы добавить еще одно решение - функциональный путь ES5:

function sortObject(obj) {
    return Object.keys(obj).sort().reduce(function (result, key) {
        result[key] = obj[key];
        return result;
    }, {});
}

Версия ES2015 выше (в формате «одна строка»):

function sortObject(o) {
    return Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {});
}

Краткое объяснение приведенных выше примеров (как указано в комментариях):

Object.keys дает нам список ключей в предоставленном объекте (obj или o), затем мы сортируем те, используя алгоритм сортировки по умолчанию, затем .reduce используется для преобразования этого массива обратно в объект, но на этот раз со всеми отсортированными ключами.

28 голосов
/ 07 августа 2018

Ребята, я образно шокирован! Конечно, все ответы несколько устарели, но никто даже не упомянул стабильность в сортировке! Так что терпите меня, я сделаю все возможное, чтобы ответить на сам вопрос и уточнить детали здесь. Так что я собираюсь извиниться, сейчас будет много читать.

Так как это 2018, я буду использовать только ES6, все полифилы доступны в документах MDN, которые я привожу в данной части.


Ответ на вопрос:

Если ваши ключи - только цифры, вы можете безопасно использовать Object.keys() вместе с Array.prototype.reduce() для возврата отсортированного объекта:

// Only numbers to show it will be sorted.
const testObj = {
  '2000': 'Articel1',
  '4000': 'Articel2',
  '1000': 'Articel3',
  '3000': 'Articel4',
};

// I'll explain what reduces does after the answer.
console.log(Object.keys(testObj).reduce((accumulator, currentValue) => {
  accumulator[currentValue] = testObj[currentValue];
  return accumulator;
}, {}));

/**
 * expected output:
 * {
 * '1000': 'Articel3',
 * '2000': 'Articel1',
 * '3000': 'Articel4',
 * '4000': 'Articel2' 
 *  } 
 */

// if needed here is the one liner:
console.log(Object.keys(testObj).reduce((a, c) => (a[c] = testObj[c], a), {}));

Однако, если вы работаете со строками, я настоятельно рекомендую объединить Array.prototype.sort() во все это:

// String example
const testObj = {
  'a1d78eg8fdg387fg38': 'Articel1',
  'z12989dh89h31d9h39': 'Articel2',
  'f1203391dhj32189h2': 'Articel3',
  'b10939hd83f9032003': 'Articel4',
};
// Chained sort into all of this.
console.log(Object.keys(testObj).sort().reduce((accumulator, currentValue) => {
  accumulator[currentValue] = testObj[currentValue];
  return accumulator;
}, {}));

/**
 * expected output:   
 * { 
 * a1d78eg8fdg387fg38: 'Articel1',
 * b10939hd83f9032003: 'Articel4',
 * f1203391dhj32189h2: 'Articel3',
 * z12989dh89h31d9h39: 'Articel2' 
 * }
 */

// again the one liner:
console.log(Object.keys(testObj).sort().reduce((a, c) => (a[c] = testObj[c], a), {}));

Если кому-то интересно, что делает уменьшение:

// Will return Keys of object as an array (sorted if only numbers or single strings like a,b,c).
Object.keys(testObj)

// Chaining reduce to the returned array from Object.keys().
// Array.prototype.reduce() takes one callback 
// (and another param look at the last line) and passes 4 arguments to it: 
// accumulator, currentValue, currentIndex and array
.reduce((accumulator, currentValue) => {

  // setting the accumulator (sorted new object) with the actual property from old (unsorted) object.
  accumulator[currentValue] = testObj[currentValue];

  // returning the newly sorted object for the next element in array.
  return accumulator;

  // the empty object {} ist the initial value for  Array.prototype.reduce().
}, {});

Если необходимо, вот пояснение для одного вкладыша:

Object.keys(testObj).reduce(

  // Arrow function as callback parameter.
  (a, c) => 

  // parenthesis return! so we can safe the return and write only (..., a);
  (a[c] = testObj[c], a)

  // initial value for reduce.
  ,{}
);

Почему сортировка немного сложна:

Вкратце Object.keys() вернет массив в том же порядке, что и обычный цикл:

const object1 = {
  a: 'somestring',
  b: 42,
  c: false
};

console.log(Object.keys(object1));
// expected output: Array ["a", "b", "c"]

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

Sidenote - вы также можете использовать Object.keys() для массивов, имейте в виду, что индекс будет возвращен:

// simple array
const arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']

Но это не так легко показать на этих примерах, объекты реального мира могут содержать цифры и буквы или даже символы (пожалуйста, не делайте этого).

Вот пример со всеми из них в одном объекте:

// This is just to show what happens, please don't use symbols in keys.
const testObj = {
  '1asc': '4444',
  1000: 'a',
  b: '1231',
  '#01010101010': 'asd',
  2: 'c'
};

console.log(Object.keys(testObj));
// output: [ '2', '1000', '1asc', 'b', '#01010101010' ]

Теперь, если мы используем Array.prototype.sort() в массиве выше, выходные данные изменятся:

console.log(Object.keys(testObj).sort());
// output: [ '#01010101010', '1000', '1asc', '2', 'b' ]

Вот цитата из документации:

Метод sort () сортирует элементы массива на месте и возвращает массив. Сортировка не обязательно стабильна. Порядок сортировки по умолчанию в соответствии со строкой кода Unicode.

Трудно гарантировать временную и пространственную сложность вида зависит от реализации.

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


Так в чем же дело?

Ну, есть две статьи, которые должен понять каждый программист:

Алгоритм на месте :

В компьютерной науке алгоритм на месте - это алгоритм, который преобразует входные данные без использования вспомогательной структуры данных. Однако для вспомогательных переменных допускается небольшое количество дополнительного пространства для хранения. Входные данные обычно перезаписываются выходными данными при выполнении алгоритма. Алгоритм на месте обновляет входную последовательность только путем замены или замены элементов. Алгоритм, который не на месте, иногда называют не на месте или не на месте.

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

Алгоритм сортировки

Стабильные алгоритмы сортировки сортируют идентичные элементы в том же порядке, что они появляются на входе. При сортировке некоторых видов данных, только часть данных проверяется при определении порядка сортировки. Например, в примере сортировки карт справа карты сортируются их рангом, и их иск игнорируется. Это позволяет возможность нескольких разных правильно отсортированных версий Оригинальный список. Стабильные алгоритмы сортировки выбирают один из них, согласно следующему правилу: если два элемента сравниваются как равные, какдве 5 карт, то их относительный порядок будет сохранен, так что если одна из них была перед другой на входе, она также будет стоять перед другой на выходе.

enter image description here

Пример стабильной сортировки на игральных картах.Когда карты отсортированы по рангу со стабильной сортировкой, две 5 должны оставаться в том же порядке в отсортированном выводе, в котором они были изначально. Когда они сортируются с нестабильной сортировкой, эти 5 могут оказаться в противоположномпорядок в отсортированном выводе.

Это показывает, что сортировка верна, но она изменилась.Таким образом, в реальном мире, даже если сортировка правильная, мы должны убедиться, что получаем то, что ожидаем!Это очень важно, имейте это в виду.Дополнительные примеры JavaScript можно найти в Array.prototype.sort () - docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

28 голосов
/ 11 октября 2012

Это работает для меня

/**
 * Return an Object sorted by it's Key
 */
var sortObjectByKey = function(obj){
    var keys = [];
    var sorted_obj = {};

    for(var key in obj){
        if(obj.hasOwnProperty(key)){
            keys.push(key);
        }
    }

    // sort keys
    keys.sort();

    // create new array based on Sorted Keys
    jQuery.each(keys, function(i, key){
        sorted_obj[key] = obj[key];
    });

    return sorted_obj;
};
19 голосов
/ 14 октября 2015

Это старый вопрос, но, судя по ответу Матиаса Биненса, я сделал короткую версию для сортировки текущего объекта без особых накладных расходов.

    Object.keys(unordered).sort().forEach(function(key) {
        var value = unordered[key];
        delete unordered[key];
        unordered[key] = value;
    });

после выполнения кода для самого «неупорядоченного» объекта ключи будут отсортированы в алфавитном порядке.

17 голосов
/ 05 апреля 2018

вот 1 вкладыш

var data = { zIndex:99,
             name:'sravan',
             age:25, 
             position:'architect',
             amount:'100k',
             manager:'mammu' };

console.log(Object.entries(data).sort().reduce( (o,[k,v]) => (o[k]=v,o), {} ));
16 голосов
/ 23 июня 2013

Используя lodash, это будет работать:

some_map = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' }

// perform a function in order of ascending key
_(some_map).keys().sort().each(function (key) {
  var value = some_map[key];
  // do something
});

// or alternatively to build a sorted list
sorted_list = _(some_map).keys().sort().map(function (key) {
  var value = some_map[key];
  // return something that shall become an item in the sorted list
}).value();

Просто пища для размышлений.

15 голосов
/ 07 августа 2013

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

(function(s){var t={};Object.keys(s).sort().forEach(function(k){t[k]=s[k]});return t})({b:2,a:1,c:3})
10 голосов
/ 17 марта 2019

Это 2019 год, и у нас есть 2019 способ решить эту проблему:)

Object.fromEntries(Object.entries({b: 3, a:8, c:1}).sort())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...