Сортуйте об’єкт JavaScript за ключем


532

Мені потрібно сортувати об’єкти JavaScript за ключем.

Звідси наступне:

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

Стають:

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


38
Ще в 2011 році (коли було розміщено це запитання) специфікація ECMAScript сказала, що об’єкти JavaScript не мають притаманного порядку - спостережуваний порядок залежав від реалізації і тому не можна покладатися на нього. Однак виявляється, що всі двигуни JavaScript реалізували більш-менш однакову семантику, тому тепер вони були стандартизовані в ES6 . Як результат, багато відповідей, наведених нижче, використовувались як правильні відповідно до специфікації, але зараз є невірними.
Mathias Bynens

коротко кажучи, використовуйте відсортовану stringify, коли вам потрібно порівняти або хеш-результати: npmjs.com/package/json-stable-stringify
exebook

Зважаючи на те, що об’єкти - це лише карти чи дикти залежно від вашої мови, чому б ви зробили це мало, немає жодних причин. Що сказано, як правило, порядок їх введення в карту насправді є порядком, в якому вони проживають під час строфікації. Так, якщо ви створили нову карту та призначили значення на основі списованого списку ключів, ви знайдете впорядковану карту на основі клавіш
Fallenreaper

Зверніть увагу , що з тих пір , Object.entriesі Object.fromEntriesбули додані в JS, це може бути досягнуто з добре коротким однострочнікі:Object.fromEntries(Object.entries(obj).sort())
Майком «Pomax» Kamermans

Відповіді:


471

Інші відповіді на це питання застаріли, ніколи не відповідали реальності впровадження, і офіційно стали неправильними тепер, коли опубліковано специфікацію ES6 / ES2015.


Дивіться розділ про порядок ітерації властивостей у Дослідженні ES6 від Axel Rauschmayer :

Усі методи, що повторюють ключі властивостей, роблять це в одному порядку:

  1. Спочатку всі індекси масиву, відсортовані за чисельністю.
  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.


5
Я дійсно не можу побачити різницю у вашому коді та верхній відповіді тут, окрім використання трохи іншого циклічного методу. Незалежно від того, чи можна об’єкти можна сказати "упорядкованими" чи ні, це не має значення. Відповідь на це питання все одно. Опублікована специфікація лише підтверджує відповіді тут.
Філ

6
FYI, було уточнено, що порядок перерахування властивостей досі не визначений: esdiscuss.org/topic/…
Фелікс Клінг

6
@ Phil_1984_ Ця відповідь та найвища відповідь дуже відрізняються. Питання ОП полягало в тому, як сортувати об’єкт буквально. Відповідь вгорі говорить про те, що ви не можете, а потім дає вирішення шляхом зберігання відсортованих ключів у масиві, а потім ітерації та друкує пари значень ключів із відсортованого масиву. У цій відповіді стверджується, що порядок об'єктних літералів тепер сортується, і його приклад зберігає відсортовані значення ключа назад до об'єкта буквально, а потім друкує відсортований об’єкт безпосередньо. Зі сторони, було б непогано, якби пов’язаний сайт все ще існував.
Чемберлен

6
Обидва відповіді просто використовують функцію Array.sort, щоб спочатку сортувати клавіші. ОП просить сортувати "об’єкт JavaScript" і просто використовує нотацію JavaScript Object Notation (JSON) для опису двох об'єктів. Ці 2 об'єкти є логічно однаковим, тому сортування не має значення. Я думаю, що відповідь на це пояснює це набагато краще. Сказати, що "всі інші відповіді зараз офіційно невірні", для мене занадто екстремально, особливо з розірваним посиланням. Я думаю, що проблема полягає в тому, що "ця нова специфікація ES6" дає ілюзію, що в об'єктах Javascript впорядкований список ключів, що просто не відповідає дійсності.
Філ

1
Додайте, що це рішення не підтримується різноманітними сучасними браузерами (google "caniuse ES6"). Використання цієї відповіді ризикує знайти важкі помилки лише у певних браузерах (наприклад, Safari, коли Chrome усе добре).
Мануель Арвед Шмідт

244

Об'єкти 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 .


2
@MarcelKorpel Є такий предмет, як об'єкт JSON. Перевірте розділ 8 офіційного JSON RFC: ietf.org/rfc/rfc4627.txt
Павло

8
@Paulpro слід зазначити дві речі щодо цього RFC: по-перше, в цей момент йому вже 7 років, і словниковий запас змінюється з часом; по-друге, "Ця примітка надає інформацію для Інтернет-спільноти. У ній не визначено будь-якого Інтернет-стандарту". Будь-яка послідовність символів представляє літеральний об'єкт JavaScript або текст JSON, залежить від контексту / використання. Термін "об'єкт JSON" поєднує і робить розрізнення неоднозначним у згубному відношенні. Позбавимося від неточної термінології та скористайтеся точнішим терміном, де це можливо. Я не бачу причин робити інше. Слова мають значення.
Метт Бал

6
@MattBall IMO JSON Object - дуже точний термін для рядка, подібно до {"a", 1}того, як JSON Array є точним терміном для рядка [1]. Корисно мати можливість спілкуватися, вимовляючи такі речі, як третій об’єкт у моєму масиві, коли у вас є рядок [{x: 1}, {y: 2}, {z: 3}], тому я дуже віддаю перевагу "Це не об’єкт JSON", коли коментую літературу Javascript, а не тоді "Немає такого річ як об'єкт JSON ", що просто викличе більше плутанини та труднощів із спілкуванням пізніше, коли ОП фактично працює з JSON.
Пол

3
@Paulpro Я не повинен погодитися. {"a", 1}є або об'єктним літералом, або текстом JSON (він же - рядок JSON, якщо ви хочете). Який це залежить від контексту, перший, якщо він з’являється дослівно у вихідному коді JavaScript, другий, якщо це рядок, який потрібно передати в аналізатор JSON для подальшого використання. Існують реальні відмінності між ними, коли мова йде про дозволений синтаксис, правильне використання та серіалізацію.
Метт Бал

4
Тепер, коли ES6 / ES2015 завершено, ця відповідь офіційно стала неправильною. Дивіться мою відповідь для отримання додаткової інформації.
Матіас Байненс

172

Багато людей згадують, що "об'єкти не можна сортувати" , але після цього вони дають вам рішення, яке працює. Парадокс, чи не так?

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

І я думаю, що ми могли б додати ще одне рішення - функціональний спосіб ES5:

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

Версія ES2015 вище (відформатована до "однолінійного"):

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

Коротке пояснення вищенаведених прикладів (як запитують у коментарях):

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


7
@Pointy Така поведінка завжди доступна у всіх основних браузерах і стандартизована в ES6 / ES2015 . Я б сказав, що це хороша порада.
Mathias Bynens

3
Це найпростіший і стисліший спосіб виконання завдання в EcmaScript v5. Трохи запізнюємось на партію, але це має бути прийнята відповідь.
Стівен де Салас

2
"Вони є, тому що в більшості реалізацій браузера значення в об'єктах зберігаються в тому порядку, в якому вони були додані" Хоча лише для нечислових властивостей. Також зауважте, що досі не існує гарантії, в якій послідовності повторюються властивості (наприклад, через for...in).
Фелікс Клінг

2
Приємно, що ви пояснили, чому це працює, це зробив урок для мене. Дякую!
ола

5
Мій лайтер скаржився на той однолінійний (повертаючи завдання), але цей працює для мене і мені легше читати:Object.keys(dict).sort().reduce((r, k) => Object.assign(r, { [k]: dict[k] }), {});
АКС.

68

Хлопці, я образно шокований! Впевнені, що всі відповіді дещо старі, але ніхто не згадав про стабільність у сортуванні! Тож потерпіть зі мною, я постараюся зробити все можливе, щоб відповісти на запитання самого себе і розібратися тут у деталях. Тож я зараз вибачусь, читати буде багато.

Оскільки в 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 карт, то їх відносний порядок буде збережений, так що якщо один входив до іншого у введенні, він також прийти перед іншим у виході.

введіть тут опис зображення

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

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


3
Ви гортаєте рок, дякую за цю неймовірну відповідь. Один з найкращих, що я бачив на SO. Ура.
Гавін

Якби тільки ти міг надати химерний метод, який слід використати наприкінці. Хоча чудова відповідь!
ммм

@momomo проблема полягає в тому, що в залежності від того, що ви очікуєте від сортування, немає правильного методу. Однак ви можете просто використовувати цей шматок коду з моєї відповіді: Object.keys(testObj).sort().reduce((a, c) => (a[c] = testObj[c], a), {}).
Мегажин

Чи не стабільність цього роду не застосовується до цього питання: ми сортуємо за об'єктним ключем, а ключ унікальний. (Щоб продовжити приклад вашої картки: ніколи в упаковці не може бути двох 5-х, навіть якщо вони мають різні костюми.)
Даррен Кук,

@DarrenCook гарне запитання! Ви маєте рацію, що ніколи не буде однакового ключа в одному об’єкті. Однак стабільність складніше, ніж просто унікальність ключа. Більшу частину часу масив включається в сортування об’єктів. І саме тоді все може стати нестабільним. Уявіть карткову гру з 5 гравцями. Кожна рука представлена ​​масивом (для збереження індивідуального сортування руки) та картками як об'єктами. Якщо ваша карта виглядає таким чином {5: 'hearts'}або {5: 'spades'}ви почнете сортувати масив, вона стане потенційно нестабільною в іграх, таких як роммі. Не говорити на різних мовах.
Мегажин

29

Це працює для мене

/**
 * 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;
};

10
Це насправді правильна відповідь на відповідне питання. Для спрощеної версії з допомогою підкреслення, см: jsfiddle.net/wPjaQ/1
підкореневе

6
@radicand Ні, ця відповідь не є правильною. Він повертає новий об'єкт, який також не має порядку.
Пол

3
@radicand Це також не відбувається на практиці. Не існує такого поняття, як порядок на клавішах об'єктів, тож як ви можете сказати, що на практиці це дає вам об’єкт у відсортованому порядку? Це дійсно просто дає вам назад неповну копію об'єкта ви передаєте в.
Paul

9
Це супер неправильно. Можливо, це працює зараз, але він порушиться в іншому веб-браузері або в іншому веб-переглядачі. Веб-браузери можуть рандомізувати об’єктні ключі для безпеки, або коли ви заповнюєте об'єкт, вони розміщуватимуть значення в різні відрізки пам'яті залежно від клавіш, які повернуть інший порядок. Якщо це трапиться на роботу, вам просто пощастить.
Йоберт

11
Він також має непотрібне використання jQuery.
RobG

25

Це 2019 рік, і у нас є спосіб вирішити це в 2019 році :)

Object.fromEntries(Object.entries({b: 3, a:8, c:1}).sort())

2
Як ми сортуємо вкладені об’єкти за ключем?
a2441918

@ a2441918 Так само, як ви робили з функцією sort (). Подивіться: developer.mozilla.org/de/docs/Web/JavaScript/Reference/… Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). Sort ((k, j ) => k - j))
користувач2912903

Для користувачів TypeScript це для нас ще не доступно, див .: github.com/microsoft/TypeScript/isissue/30933
tsujp

Хороший однолінійний вклад, але як сортувати клавіші в регістрі?
theMaxx

1
@theMaxx Використовуйте власну функцію для сортування, наприклад: `` `Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). sort (([key1, val1], [key2, val2]) => key1.toLowerCase (). localeCompare (key2.toLowerCase ())) `` `
Бен

22

ось 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), {} ));


Що за чорт цей божевільний синтаксис? (o[k] = v, o). Чому це навіть працює, де я можу знайти документи про це? Очевидно, повертає найправіший параметр, але чому?
ntaso

1
@ntaso here
Джеймс

Коротка функція спершу o[k]дорівнює, vа потім повертаєтьсяo
Тахсін Туркоз

19

Це давнє запитання, але, беручи відповідь на відповідь Матіаса Байненса, я створив коротку версію, щоб сортувати поточний об’єкт, без особливих накладних витрат.

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

після виконання коду, сам "не упорядкований" об'єкт матиме ключі в алфавітному порядку.


17

Використовуючи 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

Припустимо, він може бути корисним у відладчику VisualStudio, який показує невпорядковані властивості об'єкта.

(function(s){var t={};Object.keys(s).sort().forEach(function(k){t[k]=s[k]});return t})({b:2,a:1,c:3})

Тож велике спасибі a loooot
Mugiwara

Приємно! Дякую за це лаконічне рішення.
Con Antonakos

9

Версія підкреслення :

function order(unordered)
{
return _.object(_.sortBy(_.pairs(unordered),function(o){return o[0]}));
}

Якщо ви не довіряєте вашому веб-переглядачу для того, щоб зберігати порядок ключів, я настійно пропоную покластися на упорядкований масив парних масивів з значенням-значенням.

_.sortBy(_.pairs(c),function(o){return o[0]})

Краще:_.object(_.sortBy(_.pairs(unordered), _.first))
Афанасій Куракін

8
function sortObjectKeys(obj){
    return Object.keys(obj).sort().reduce((acc,key)=>{
        acc[key]=obj[key];
        return acc;
    },{});
}

sortObjectKeys({
    telephone: '069911234124',
    name: 'Lola',
    access: true,
});

Можливо, краще додати пояснення вашого коду.
aristotll

1
Отримує ключі об’єкта, тому це масив рядків, я сортую () їх, і як це масив рядків (ключів), я зменшу їх (з допомогою зменшення () з js Array). Спочатку ac є порожнім об'єктом {} (останній аргумент редуктора), а редуктор (зворотний виклик) присвоює порожньому об'єкту значення вихідного об'єкта з упорядкованою послідовністю ключів.
користувач3286817

8

Можливо, трохи елегантніша форма:

 /**
     * Sorts a key-value object by key, maintaining key to data correlations.
     * @param {Object} src  key-value object
     * @returns {Object}
     */
var ksort = function ( src ) {
      var keys = Object.keys( src ),
          target = {};
      keys.sort();
      keys.forEach(function ( key ) {
        target[ key ] = src[ key ];
      });
      return target;
    };


// Usage
console.log(ksort({
  a:1,
  c:3,
  b:2  
}));

PS та те саме з синтаксисом ES6 +:

function ksort( src ) {
  const keys = Object.keys( src );
  keys.sort();
  return keys.reduce(( target, key ) => {
        target[ key ] = src[ key ];
        return target;
  }, {});
};

це нічого не сортує. ви все одно повертаєте об’єкт. ви не можете гарантувати, що об’єкти в цільовій мірі насправді матимуть будь-який порядок. вам потрібно повернути масив. джеєзус.
ммм

єдине, що ви робите тут, - це забезпечити це набором, неоптимальним чином.
ммм

7

рекурсивне сортування для вкладених об'єктів та масивів

function sortObjectKeys(obj){
    return Object.keys(obj).sort().reduce((acc,key)=>{
        if (Array.isArray(obj[key])){
            acc[key]=obj[key].map(sortObjectKeys);
        }
        if (typeof obj[key] === 'object'){
            acc[key]=sortObjectKeys(obj[key]);
        }
        else{
            acc[key]=obj[key];
        }
        return acc;
    },{});
}

// test it
sortObjectKeys({
    telephone: '069911234124',
    name: 'Lola',
    access: true,
    cars: [
        {name: 'Family', brand: 'Volvo', cc:1600},
        {
            name: 'City', brand: 'VW', cc:1200, 
            interior: {
                wheel: 'plastic',
                radio: 'blaupunkt'
            }
        },
        {
            cc:2600, name: 'Killer', brand: 'Plymouth',
            interior: {
                wheel: 'wooden',
                radio: 'earache!'
            }
        },
    ]
});

Я думаю, що вам потрібно elseтам - може бути правдою Array.isArray(obj[key])і для, і дляtypeof obj[key] === 'object'
jononomo

Коли у вас є масив примітивів, ваша функція перетворює примітиви (рядок / число) у порожні об'єкти. Щоб зрозуміти це, я додав наступне право на початку вашої функції function sortObjectKeys(obj){:: if(typeof obj != 'object'){ /* it is a primitive: number/string (in an array) */ return obj; }. Для надійності я на повному старті також додав:if(obj == null || obj == undefined){ return obj; }
розпочато

4

Як вже було сказано, об'єкти не упорядковані.

Однак ...

Ви можете вважати цю фразу корисною:

var o = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' };

var kv = [];

for (var k in o) {
  kv.push([k, o[k]]);
}

kv.sort()

Потім ви можете перебирати через kv і робити все, що завгодно.

> kv.sort()
[ [ 'a', 'dsfdsfsdf' ],
  [ 'b', 'asdsad' ],
  [ 'c', 'masdas' ] ]


4

Ось чиста версія на основі лодашу, яка працює з вкладеними об'єктами

/**
 * Sort of the keys of an object alphabetically
 */
const sortKeys = function(obj) {
  if(_.isArray(obj)) {
    return obj.map(sortKeys);
  }
  if(_.isObject(obj)) {
    return _.fromPairs(_.keys(obj).sort().map(key => [key, sortKeys(obj[key])]));
  }
  return obj;
};

Було б ще чистіше, якби лодаш мав toObject()метод ...


3

Просто використовуйте lodash, щоб розпакувати карту і сортуватиBy перше значення пари та zip знову, воно поверне відсортований ключ.

Якщо ви хочете сортувати значення, змініть індекс пари на 1, а не на 0

var o = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' };
console.log(_(o).toPairs().sortBy(0).fromPairs().value())

введіть тут опис зображення


Будь ласка, скористайтеся посиланням редагування, поясніть, як працює цей код, а не просто надайте код, оскільки пояснення швидше допоможе майбутнім читачам. Див. Також Як відповісти . джерело
Джед Фокс

3

Сортування клавіш рекурсивно, зберігаючи посилання.

function sortKeys(o){
    if(o && o.constructor === Array)
        o.forEach(i=>sortKeys(i));
    else if(o && o.constructor === Object)
        Object.entries(o).sort((a,b)=>a[0]>b[0]?1:-1).forEach(e=>{
            sortKeys(e[1]);
            delete o[e[0]];
            o[e[0]] = e[1];
        });
}

Приклад:

let x = {d:3, c:{g:20, a:[3,2,{s:200, a:100}]}, a:1};
let y = x.c;
let z = x.c.a[2];
sortKeys(x);
console.log(x); // {a: 1, c: {a: [3, 2, {a: 1, s: 2}], g: 2}, d: 3}
console.log(y); // {a: [3, 2, {a: 100, s: 200}}, g: 20}
console.log(z); // {a: 100, s: 200}

Гарний фрагмент! Яка мета delete o[e[0]];там? Чи не можемо ми просто призначити?
Боянг

Схоже, лише нові призначення неіснуючих клавіш додадуть ключ в кінці. Якщо видалення прокоментується, клавіші не будуть сортуватися, принаймні, не в Chrome.
brunettdan

що має сенс. Дякую! У будь-якому випадку це щось на зразок втраченої причини, оскільки клавіші об’єктів js не мають послідовності, відповідно до специфікацій. Ми просто використовуємо obj і log функції impl подробиці
Боянг,

Так, я використовую Map, коли важливий порядок клавіш: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
brunettdan


3

Це полегшене рішення для всього, що потрібно для сортування JSON.

function sortObj(obj) {
    if (typeof obj !== "object" || obj === null)
        return obj;

    if (Array.isArray(obj))
        return obj.map((e) => sortObj(e)).sort();

    return Object.keys(obj).sort().reduce((sorted, k) => {
        sorted[k] = sortObj(obj[k]);
        return sorted;
    }, {});
}

2

Використовуйте цей код, якщо ви вклали об’єкти або якщо вклали масив obj.

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){
        var val = obj[key];
        if(val instanceof Array){
            //do for loop;
            var arr = [];
            jQuery.each(val,function(){
                arr.push(sortObjectByKey(this));
            }); 
            val = arr;

        }else if(val instanceof Object){
            val = sortObjectByKey(val)
        }
        sorted_obj[key] = val;
    });
    return sorted_obj;
};

5
Автор не заявляє, що він використовує jQuery, а також питання, позначене jQuery. Було б добре, якщо ви додасте рішення в чистому JavaScript.
русмус

Дякую @Phani, це саме те, що мені потрібно
Буде Шеппард

2

Рішення:

function getSortedObject(object) {
  var sortedObject = {};

  var keys = Object.keys(object);
  keys.sort();

  for (var i = 0, size = keys.length; i < size; i++) {
    key = keys[i];
    value = object[key];
    sortedObject[key] = value;
  }

  return sortedObject;
}

// Test run
getSortedObject({d: 4, a: 1, b: 2, c: 3});

Пояснення:

Багато режимів JavaScript зберігають значення всередині об'єкта в тому порядку, в якому вони додані.

Для сортування властивостей об’єкта за їх ключами ви можете скористатися функцією Object.keys, яка поверне масив ключів. Потім масив ключів може бути відсортований за Array.prototype.sort () який сортує елементи масиву на місці (не потрібно призначати їх новій змінній).

Після сортування ключів ви можете почати використовувати їх по одному для доступу до вмісту старого об’єкта для заповнення нового об’єкта (який зараз відсортований).

Нижче наведено приклад процедури (ви можете протестувати її у своїх цільових браузерах):

/**
 * Returns a copy of an object, which is ordered by the keys of the original object.
 *
 * @param {Object} object - The original object.
 * @returns {Object} Copy of the original object sorted by keys.
 */
function getSortedObject(object) {
  // New object which will be returned with sorted keys
  var sortedObject = {};

  // Get array of keys from the old/current object
  var keys = Object.keys(object);
  // Sort keys (in place)
  keys.sort();

  // Use sorted keys to copy values from old object to the new one
  for (var i = 0, size = keys.length; i < size; i++) {
    key = keys[i];
    value = object[key];
    sortedObject[key] = value;
  }

  // Return the new object
  return sortedObject;
}

/**
 * Test run
 */
var unsortedObject = {
  d: 4,
  a: 1,
  b: 2,
  c: 3
};

var sortedObject = getSortedObject(unsortedObject);

for (var key in sortedObject) {
  var text = "Key: " + key + ", Value: " + sortedObject[key];
  var paragraph = document.createElement('p');
  paragraph.textContent = text;
  document.body.appendChild(paragraph);
}

Примітка: Object.keys - це метод ECMAScript 5.1, але ось поліфайл для старих браузерів:

if (!Object.keys) {
  Object.keys = function (object) {
    var key = [];
    var property = undefined;
    for (property in object) {
      if (Object.prototype.hasOwnProperty.call(object, property)) {
        key.push(property);
      }
    }
    return key;
  };
}

2

Я перевів деякі перерахунки Java на об’єкти javascript.

Ці об’єкти повернули правильні масиви для мене. якщо об'єктні ключі змішаного типу (string, int, char), є проблема.

Types:

var TypeA = {
    "-1": "Any",
    "2": "2L",
    "100": "100L",
    "200": "200L",
    "1000": "1000L"
};

var TypeB = {
    "U": "Any",
    "W": "1L",
    "V": "2L",
    "A": "100L",
    "Z": "200L",
    "K": "1000L"
};


Sorted Keys(output):

Key list of TypeA -> ["-1", "2", "100", "200", "1000"]

Key list of TypeB -> ["U", "W", "V", "A", "Z", "K"]

2

Простий і читабельний фрагмент, використовуючи лодаш.

Ключ у лапки потрібно вводити лише під час виклику sortBy. Це не повинно бути в лапках у самих даних.

_.sortBy(myObj, "key")

Крім того, ваш другий параметр для відображення неправильно. Це повинно бути функцією, але використовувати pluck простіше.

_.map( _.sortBy(myObj, "key") , "value");

2

Існує чудовий проект @sindresorhus під назвою sort-keys, який працює надзвичайно.

Ви можете перевірити його вихідний код тут:

https://github.com/sindresorhus/sort-keys

Або ви можете використовувати його з npm:

$ npm install --save sort-keys

Ось також приклади коду з його readme

const sortKeys = require('sort-keys');

sortKeys({c: 0, a: 0, b: 0});
//=> {a: 0, b: 0, c: 0}

sortKeys({b: {b: 0, a: 0}, a: 0}, {deep: true});
//=> {a: 0, b: {a: 0, b: 0}}

sortKeys({c: 0, a: 0, b: 0}, {
    compare: (a, b) => -a.localeCompare(b)
});
//=> {c: 0, b: 0, a: 0}

1

Чистий відповідь JavaScript для сортування об’єкта. Це єдина відповідь, яку я знаю, що буде обробляти негативні числа. Ця функція призначена для сортування числових об'єктів.

Введення obj = {1000: {}, -1200: {}, 10000: {}, 200: {}};

function osort(obj) {
var keys = Object.keys(obj);
var len = keys.length;
var rObj = [];
var rK = [];
var t = Object.keys(obj).length;
while(t > rK.length) {
    var l = null;
    for(var x in keys) {
        if(l && parseInt(keys[x]) < parseInt(l)) {
            l = keys[x];
            k = x;
        }
        if(!l) { // Find Lowest
            var l = keys[x];
            var k = x;
        }
    }
    delete keys[k];
    rK.push(l);
}

for (var i = 0; i < len; i++) {

    k = rK[i];
    rObj.push(obj[k]);
}
return rObj;
}

Виведенням буде об'єкт, відсортований за цими числами з новими клавішами, починаючи з 0.


1

Просто, щоб спростити його і зробити більш зрозумілою відповідь від Метта Бал

//your object
var myObj = {
    b : 'asdsadfd',
    c : 'masdasaf',
    a : 'dsfdsfsdf'
  };

//fixed code
var keys = [];
for (var k in myObj) {
  if (myObj.hasOwnProperty(k)) {
    keys.push(k);
  }
}
keys.sort();
for (var i = 0; i < keys.length; i++) {
  k = keys[i];
  alert(k + ':' + myObj[k]);
}


1

Не впевнений, чи відповідає це на питання, але це те, що мені було потрібно.

Maps.iterate.sorted = function (o, callback) {
    var keys = Object.keys(o), sorted = keys.sort(), k; 
    if ( callback ) {
            var i = -1;
            while( ++i < sorted.length ) {
                    callback(k = sorted[i], o[k] );
            }
    }

    return sorted;
}

Називається як:

Maps.iterate.sorted({c:1, b:2, a:100}, function(k, v) { ... } ) 

1

Єдиний рядок:

Object.entries(unordered)
  .sort(([keyA], [keyB]) => keyA > keyB)
  .reduce((obj, [key,value]) => Object.assign(obj, {[key]: value}), {})

1

найкращий спосіб це зробити

 const object =  Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {})

 //else if its in reverse just do 

 const object = Object.keys(0).reverse ()

Ви можете спочатку перетворити об’єкт, що нагадує майже масив, у реальний масив, а потім використовувати .reverse ():

Object.assign([], {1:'banana', 2:'apple', 
3:'orange'}).reverse();
// [ "orange", "apple", "banana", <1 empty slot> ]

Порожній проріз в кінці, якщо причина, тому що ваш перший індекс 1, а не 0. Ви можете видалити порожній слот за допомогою .length-- або .pop ().

Крім того, якщо ви хочете запозичити .reverse і викликати його на одному і тому ж об'єкті, він повинен бути об'єктом, що нагадує повністю масив. Тобто йому потрібна властивість довжини:

Array.prototype.reverse.call({1:'banana', 2:'apple', 
3:'orange', length:4});
// {0:"orange", 1:"apple", 3:"banana", length:4}

Зверніть увагу, що він поверне той самий об'єкт, що схожий на масив, так що це не буде реальним масивом. Потім ви можете видалити для видалення властивості довжини.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.