Ordenar objeto JavaScript por clave


532

Necesito ordenar los objetos de JavaScript por clave.

De ahí lo siguiente:

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

Se convertiría:

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


39
En 2011 (cuando se publicó esta pregunta), la especificación ECMAScript decía que los objetos de JavaScript no tienen un orden inherente: el orden observado dependía de la implementación y, por lo tanto, no se podía confiar en él. Sin embargo, resulta que todos los motores de JavaScript implementaron más o menos la misma semántica, por lo que ahora se han estandarizado en ES6 . Como resultado, muchas de las respuestas a continuación solían ser correctas según las especificaciones, pero ahora son incorrectas.
Mathias Bynens

diciendo brevemente use stringify ordenado cuando necesite comparar o analizar
exebook

Dado que los objetos son solo mapas, o dictados dependiendo de su idioma, hay poca o ninguna razón por la que haría esto. Dicho esto, en general, el orden en que se inyectan en un mapa es, de hecho, el orden en el que residen al encadenar. Por lo tanto, si creó un nuevo mapa y asignó valores basados ​​en una lista de claves clasificadas previamente, encontrará un mapa ordenado basado en claves
Fallenreaper,

Tenga en cuenta que desde entonces Object.entriesy Object.fromEntriesse agregaron a JS, esto se puede lograr con una frase muy breve:Object.fromEntries(Object.entries(obj).sort())
Mike 'Pomax' Kamermans

Respuestas:


472

Las otras respuestas a esta pregunta están desactualizadas, nunca coincidieron con la realidad de implementación, y se han vuelto oficialmente incorrectas ahora que se ha publicado la especificación ES6 / ES2015.


Consulte la sección sobre el orden de iteración de propiedades en Explorando ES6 por Axel Rauschmayer :

Todos los métodos que iteran sobre las claves de propiedad lo hacen en el mismo orden:

  1. Primero todos los índices de matriz, ordenados numéricamente.
  2. Luego, todas las claves de cadena (que no son índices), en el orden en que fueron creadas.
  3. Luego todos los símbolos, en el orden en que fueron creados.

Entonces, sí, los objetos JavaScript están de hecho ordenados, y el orden de sus claves / propiedades se puede cambiar.

Así es como puede ordenar un objeto por sus claves / propiedades, alfabéticamente:

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"}'

Use en varlugar de constpor compatibilidad con motores ES5.


55
Realmente no puedo ver una diferencia en su código y la respuesta principal aquí, aparte de usar una técnica de bucle ligeramente diferente. Si se puede decir que los objetos están "ordenados" o no, parece irrelevante. La respuesta a esta pregunta sigue siendo la misma. La especificación publicada simplemente confirma las respuestas aquí.
Phil

66
Para su información, se aclaró que el orden de enumeración de las propiedades aún no está definido: esdiscuss.org/topic/…
Felix Kling

66
@ Phil_1984_ Esta respuesta y la respuesta más votada son muy diferentes. La pregunta de OP era cómo ordenar un objeto literal. La respuesta más votada dice que no puede, luego brinda una solución al almacenar las claves ordenadas en una matriz, luego iterar e imprimir pares de valores de clave desde la matriz ordenada. Esta respuesta afirma que el orden de los literales de objeto ahora se puede ordenar y su ejemplo almacena los valores de clave ordenados de nuevo en un literal de objeto, luego imprime el objeto ordenado directamente. En una nota al margen, sería bueno si el sitio vinculado aún existiera.
cchamberlain

66
Ambas respuestas simplemente usan la función Array.sort para ordenar las claves primero. El OP está pidiendo ordenar un "objeto JavaScript" y simplemente está usando la notación de objetos JavaScript (JSON) para describir los 2 objetos. Estos 2 objetos son lógicamente idénticos, lo que significa que la clasificación es irrelevante. Creo que la respuesta principal explica esto mucho mejor. Decir "todas las demás respuestas ahora son oficialmente incorrectas" es demasiado extremo para mí, especialmente con un enlace roto. Creo que el problema es que "esta nueva especificación ES6" está dando la ilusión de que los objetos Javascript tienen una lista ordenada de claves que simplemente no es verdad.
Phil

1
Agregue que esta solución no es compatible con una variedad de navegadores modernos (google "caniuse ES6"). El uso de estas respuestas conlleva riesgos de errores difíciles de encontrar solo en ciertos navegadores (por ejemplo, Safari cuando Chrome está bien).
Manuel Arwed Schmidt

244

Los objetos JavaScript 1 no están ordenados. No tiene sentido tratar de "ordenarlos". Si desea iterar sobre las propiedades de un objeto, puede ordenar las claves y luego recuperar los valores asociados:

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]);
}


Implementación alternativa usando Object.keysfantasía:

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 No para ser pedante, pero no existe un objeto JSON .


2
@MarcelKorpel Existe un objeto JSON. Consulte la sección 8 del RFC oficial de JSON: ietf.org/rfc/rfc4627.txt
Paul

8
@Paulpro dos cosas a tener en cuenta sobre ese RFC: primero, tiene 7 años en este momento, y el vocabulario cambia con el tiempo; segundo, "Este memo proporciona información para la comunidad de Internet. No especifica ningún estándar de Internet de ningún tipo". Si una secuencia dada de caracteres representa un objeto de JavaScript literal o un texto JSON depende del contexto / uso. El término "objeto JSON" se combina y hace que la distinción sea ambigua de manera perjudicial. Eliminemos la terminología imprecisa y usemos el término más preciso siempre que sea posible. No veo ninguna razón para hacer lo contrario. Las palabras importan.
Matt Ball

66
@MattBall IMO JSON Object es un término muy preciso para una cadena {"a", 1}como JSON Array es un término preciso para una cadena como [1]. Es útil poder comunicarse diciendo cosas como el tercer objeto en mi matriz cuando tiene la cadena [{x: 1}, {y: 2}, {z: 3}], por lo que prefiero "Eso no es un objeto JSON" al comentar sobre un literal Javascript, en lugar de "No existe tal cosa como un objeto JSON ", que solo causará más confusión y dificultades de comunicación más adelante cuando el OP realmente esté trabajando con JSON.
Paul

3
@Paulpro Debo estar en desacuerdo. {"a", 1}es un objeto literal o un texto JSON (también conocido como cadena JSON, si realmente lo prefiere). Lo que depende del contexto, el primero si aparece literalmente dentro del código fuente de JavaScript, el segundo si es una cadena que debe pasarse a un analizador JSON para seguir utilizándose. Existen diferencias reales entre los dos cuando se trata de sintaxis permitida, uso correcto y serialización.
Matt Ball

44
Ahora que se finalizó ES6 / ES2015, esta respuesta se ha vuelto oficialmente incorrecta. Vea mi respuesta para más información.
Mathias Bynens

172

Mucha gente ha mencionado que "los objetos no se pueden ordenar" , pero después de eso le están dando una solución que funciona. Paradoja, ¿no es así?

Nadie menciona por qué esas soluciones están funcionando. Lo son, porque en la mayoría de las implementaciones del navegador los valores en los objetos se almacenan en el orden en que se agregaron. Es por eso que si crea un nuevo objeto a partir de una lista ordenada de claves, está devolviendo un resultado esperado.

Y creo que podríamos agregar una solución más: la forma funcional ES5:

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

Versión ES2015 de arriba (formateada para "one-liner"):

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

Breve explicación de los ejemplos anteriores (como se pide en los comentarios):

Object.keysnos está dando una lista de claves en el objeto proporcionado ( objo o), luego ordenamos las que usan el algoritmo de clasificación predeterminado, luego .reducese usa para convertir esa matriz nuevamente en un objeto, pero esta vez con todas las claves ordenadas.


77
@Pointy Este comportamiento siempre ha estado disponible en todos los principales navegadores, y se ha estandarizado en ES6 / ES2015 . Yo diría que este es un buen consejo.
Mathias Bynens

3
Esta es la forma más simple y concisa de realizar la tarea en EcmaScript v5. Un poco tarde para la fiesta, pero debería ser la respuesta aceptada.
Steven de Salas

2
"Lo son, porque en la mayoría de las implementaciones del navegador los valores en los objetos se almacenan en el orden en que se agregaron" Sin embargo, solo para propiedades no numéricas. También tenga en cuenta que todavía no hay garantía en qué orden se repiten las propiedades (por ejemplo, a través de for...in).
Felix Kling

2
Fue amable de su parte explicar por qué está funcionando, fue la lección para mí. ¡Gracias!
ola

55
Mi linter se quejó de esa frase (devolviendo una tarea), pero esta funciona para mí y es más fácil de leer:Object.keys(dict).sort().reduce((r, k) => Object.assign(r, { [k]: dict[k] }), {});
aks.

68

Chicos, estoy figurativamente sorprendido! ¡Seguro que todas las respuestas son algo viejas, pero nadie mencionó la estabilidad en la clasificación! Así que tengan paciencia conmigo, haré todo lo posible para responder la pregunta en sí y entrar en detalles aquí. Así que voy a disculparme ahora, será mucho para leer.

Como es 2018, solo usaré ES6, los Polyfills están disponibles en los documentos de MDN, que vincularé en la parte dada.


Respuesta a la pregunta:

Si sus claves son solo números, puede usarlas Object.keys()con seguridad Array.prototype.reduce()para devolver el objeto ordenado:

// 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), {}));

Sin embargo, si está trabajando con cadenas, le recomiendo encadenar Array.prototype.sort()todo esto:

// 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), {}));

Si alguien se pregunta qué reduce:

// 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().
}, {});

Si es necesario, aquí está la explicación del único revestimiento:

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.
  ,{}
);

Por qué ordenar es un poco complicado:

En resumen Object.keys(), devolverá una matriz en el mismo orden que obtenemos con un bucle normal:

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

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

Object.keys () devuelve una matriz cuyos elementos son cadenas correspondientes a las propiedades enumerables que se encuentran directamente sobre el objeto. El orden de las propiedades es el mismo que el dado al recorrer manualmente las propiedades del objeto.

Nota al margen: también se puede usar Object.keys()en matrices, tenga en cuenta que se devolverá el índice:

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

Pero no es tan fácil como se muestra en esos ejemplos, los objetos del mundo real pueden contener números y caracteres alfabéticos o incluso símbolos (por favor, no lo haga).

Aquí hay un ejemplo con todos ellos en un objeto:

// 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' ]

Ahora, si usamos Array.prototype.sort()en la matriz de arriba, la salida cambia:

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

Aquí hay una cita de los documentos:

El método sort () ordena los elementos de una matriz en su lugar y devuelve la matriz. El tipo no es necesariamente estable. El orden de clasificación predeterminado es de acuerdo con los puntos de código Unicode de cadena.

La complejidad de tiempo y espacio de este tipo no se puede garantizar, ya que depende de la implementación.

Debe asegurarse de que uno de ellos le devuelva el resultado deseado. En los ejemplos de Reallife, la gente tiende a mezclar cosas especialmente si usa diferentes entradas de información como API y bases de datos juntas.


¿Así que cuál es el problema?

Bueno, hay dos artículos que todo programador debe entender:

Algoritmo en el lugar :

En informática, un algoritmo in situ es un algoritmo que transforma la entrada sin utilizar una estructura de datos auxiliar. Sin embargo, se permite una pequeña cantidad de espacio de almacenamiento adicional para las variables auxiliares. La entrada generalmente se sobrescribe con la salida a medida que se ejecuta el algoritmo. El algoritmo in situ actualiza la secuencia de entrada solo mediante el reemplazo o el intercambio de elementos. Un algoritmo que no está en el lugar a veces se llama no en el lugar o fuera de lugar.

Así que, básicamente, nuestra matriz anterior se sobrescribirá. Esto es importante si desea mantener la matriz anterior por otros motivos. Así que ten esto en cuenta.

Algoritmo de clasificación

Los algoritmos de ordenación estable ordenan elementos idénticos en el mismo orden en que aparecen en la entrada. Al ordenar algunos tipos de datos, solo se examina parte de los datos al determinar el orden de clasificación. Por ejemplo, en el ejemplo de clasificación de cartas a la derecha, las cartas se ordenan por su rango y se ignora su palo. Esto permite la posibilidad de múltiples versiones diferentes ordenadas correctamente de la lista original. Los algoritmos de clasificación estable eligen uno de estos, de acuerdo con la siguiente regla: si dos elementos se comparan como iguales, como las dos 5 cartas, entonces se mantendrá su orden relativo, de modo que si uno se antepone al otro en la entrada, también venir antes que el otro en la salida.

ingrese la descripción de la imagen aquí

Un ejemplo de clasificación estable en naipes. Cuando las tarjetas se ordenan por rango con una clasificación estable, las dos 5 deben permanecer en el mismo orden en la salida ordenada en la que se encontraban originalmente. Cuando se clasifican con una clasificación no estable, las 5 pueden terminar en el lado opuesto orden en la salida ordenada.

Esto muestra que la clasificación es correcta pero cambió. Entonces, en el mundo real, incluso si la clasificación es correcta, ¡debemos asegurarnos de obtener lo que esperamos! Esto es muy importante, tenga esto en cuenta también. Para obtener más ejemplos de JavaScript, consulte Array.prototype.sort () - documentos: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort


3
Flippin rock, gracias por esta increíble respuesta. Uno de los mejores que he visto en SO. Salud.
Gavin

Si tan solo pudieras proporcionar un método para usar al final. Gran respuesta sin embargo!
mmm

@momomo el problema es que, dependiendo de lo que espere de la clasificación, no hay un método correcto. Sin embargo, usted puede simplemente utilizar este pedazo de código de mi respuesta: Object.keys(testObj).sort().reduce((a, c) => (a[c] = testObj[c], a), {}).
Megajin

La estabilidad del tipo no es aplicable a esta pregunta: estamos ordenando por clave de objeto, y la clave es única. (Para ampliar su ejemplo de tarjeta: nunca puede haber dos 5 en el paquete, incluso si son de diferentes palos.)
Darren Cook

@DarrenCook buena pregunta! Tienes razón, nunca habrá la misma clave en un objeto. Sin embargo, la estabilidad es más compleja que solo la singularidad de una clave. La mayoría de las veces se incluye una matriz en la clasificación de objetos. Y es entonces cuando todo puede volverse inestable. Imagina un juego de cartas con 5 jugadores. Cada mano está representada por una matriz (para mantener una clasificación individual de manos) y las cartas como objetos. Si su tarjeta se ve así {5: 'hearts'}o {5: 'spades'}si comienza a ordenar la matriz, se volverá potencialmente inestable en juegos como rummy. No hablar de diferentes idiomas.
Megajin

29

Esto funciona para mi

/**
 * 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
Esta es realmente la respuesta correcta a la pregunta en cuestión. Para ver una versión simplificada que utiliza Underscore, consulte: jsfiddle.net/wPjaQ/1
radicand

66
@radicand No, esta respuesta no es correcta. Devuelve un nuevo objeto, que tampoco tiene orden.
Paul

3
@radicand Tampoco en la práctica. No existe el orden en las teclas de un objeto, entonces, ¿cómo puede decir que en la práctica esto le da un objeto en orden? Realmente solo te devuelve una copia superficial del objeto que pasas.
Paul

99
Esto está súper mal. Puede que funcione por ahora, pero se romperá en un navegador web diferente o en una carga de página diferente en el mismo navegador. Los navegadores pueden aleatorizar las claves de los objetos por seguridad o, a medida que llene un objeto, colocará los valores en diferentes segmentos de memoria dependiendo de las claves, lo que devolverá un orden diferente. Si esto sucede, es una suerte para ti.
Yobert

11
También tiene un uso innecesario de jQuery.
RobG

25

Es 2019 y tenemos una forma de resolver esto en 2019 :)

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

2
¿Cómo clasificamos los objetos anidados por clave?
a2441918

@ a2441918 De la misma manera que lo haría con la función sort (). Echa un vistazo: developer.mozilla.org/de/docs/Web/JavaScript/Reference/… Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). Sort ((k, j ) => k - j))
usuario2912903

Para los usuarios de TypeScript, esto aún no está disponible para nosotros, ver: github.com/microsoft/TypeScript/issues/30933
tsujp

Bonito, pero ¿cómo ordenar las teclas sin distinción entre mayúsculas y minúsculas?
theMaxx

1
@theMaxx Use una función personalizada para ordenar, algo como: `` `Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). sort (([key1, val1], [key2, val2]) => key1.toLowerCase (). localeCompare (key2.toLowerCase ()))) `` `
Ben

22

aquí está el trazador de líneas 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), {} ));


¿Qué diablos es esta sintaxis loca? (o[k] = v, o). ¿Por qué funciona esto? ¿Dónde puedo encontrar documentos al respecto? Obviamente, devuelve el parámetro más a la derecha, pero ¿por qué?
ntaso

1
@ntaso aquí
James

La función corta primero o[k]iguala vy luego regresao
Tahsin Turkoz

19

Esta es una vieja pregunta, pero siguiendo el ejemplo de la respuesta de Mathias Bynens, hice una versión corta para ordenar el objeto actual , sin mucha sobrecarga.

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

después de la ejecución del código, el objeto "desordenado" tendrá las claves ordenadas alfabéticamente.


17

Usando lodash esto funcionará:

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();

Solo comida para pensar.


15

Suponga que podría ser útil en el depurador de VisualStudio que muestra propiedades de objeto desordenadas.

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

Muchísimas gracias, muuuucho
Mugiwara

¡Agradable! Gracias por esta sucinta solución.
Con Antonakos

9

Versión de subrayado :

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

Si no confía en su navegador para mantener el orden de las claves, le sugiero que confíe en una matriz ordenada de matrices emparejadas de valores clave.

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

Mejor:_.object(_.sortBy(_.pairs(unordered), _.first))
Afanasii Kurakin el

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,
});

Quizás sea mejor agregar alguna explicación de su código.
aristotll

1
Obtiene las claves del objeto, por lo que es una matriz de cadenas, las ordeno () y como es una matriz de cadenas (claves) las reduzco (con reduce () de js Array). El acc inicialmente es un objeto vacío {} (último argumento del reductor) y el reductor (devolución de llamada) asigna al objeto vacío los valores del obj de origen con la secuencia de teclas ordenada.
user3286817

8

Quizás una forma un poco más elegante:

 /**
     * 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 y lo mismo con la sintaxis ES6 +:

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

No es nada. Todavía estás devolviendo un objeto. no puede garantizar que los objetos en su objetivo realmente tengan ningún orden. necesitas devolver una matriz. jeeezus.
mmm

Lo único que está haciendo aquí es asegurarse de que sea un conjunto, de una manera no óptima.
mmm

7

ordenación recursiva, para objetos anidados y matrices

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!'
            }
        },
    ]
});

Creo que necesitas un elseallí, podría ser cierto para ambos Array.isArray(obj[key])y paratypeof obj[key] === 'object'
jononomo

Cuando tiene una matriz de primitivas, su función transforma las primitivas (cadena / número) en objetos vacíos. Para atrapar a este añadí la siguiente a la derecha en el comienzo de su función: function sortObjectKeys(obj){: if(typeof obj != 'object'){ /* it is a primitive: number/string (in an array) */ return obj; }. Para robustez, al comienzo completo también agregué:if(obj == null || obj == undefined){ return obj; }
retiró

4

Como ya se mencionó, los objetos no están ordenados.

Sin embargo...

Puede encontrar útil este modismo:

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

var kv = [];

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

kv.sort()

Luego, puede iterar a través de kv y hacer lo que desee.

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


4

Aquí hay una versión limpia basada en lodash que funciona con objetos anidados

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

Sería aún más limpio si lodash tuviera un toObject()método ...


3

Simplemente use lodash para descomprimir el mapa y ordenar Por el primer valor de pair y zip nuevamente, devolverá la clave ordenada.

Si desea ordenar por valor, cambie el índice de par a 1 en lugar de 0

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

ingrese la descripción de la imagen aquí


Utilice el enlace de edición para explicar cómo funciona este código y no solo dé el código, ya que es más probable que una explicación ayude a los futuros lectores. Ver también Cómo responder . fuente
Jed Fox

3

Ordena las claves de forma recursiva y conserva las referencias.

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];
        });
}

Ejemplo:

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}

Bonito fragmento! ¿Cuál es el propósito de delete o[e[0]];allí? ¿No podemos simplemente asignar?
Boyang

Parece que solo las nuevas asignaciones a claves inexistentes agregarán la clave al final. Si eliminar está comentado, las claves no se ordenarán, al menos no en Chrome.
Brunettdan

eso tiene sentido. ¡Gracias! En cualquier caso, esta es una especie de causa perdida porque las claves de objeto js no tienen secuencia, de acuerdo con las especificaciones. Solo estamos explotando los detalles implícitos de la función de registro y obj
Boyang

Sí, uso el Mapa cuando el orden de las claves es importante: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
brunettdan

3
Object.keys(unordered).sort().reduce(
    (acc,curr) => ({...acc, [curr]:unordered[curr]})
    , {}
)

3

Esta es una solución ligera para todo lo que necesito para la clasificación 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

Use este código si ha anidado objetos o si ha anidado una matriz de 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;
};

55
El autor no dice que está usando jQuery, ni la pregunta está etiquetada como jQuery. Sería bueno si agrega una solución en javascript puro.
rusmus

Gracias @Phani, esto es exactamente lo que necesitaba
Will Sheppard

2

Solución:

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});

Explicación:

Muchos tiempos de ejecución de JavaScript almacenan valores dentro de un objeto en el orden en que se agregan.

Para ordenar las propiedades de un objeto por sus claves, puede utilizar la función Object.keys que devolverá una matriz de claves. La matriz de claves se puede ordenar por Array.prototype.sort () método que clasifica los elementos de una matriz en su lugar (no es necesario asignarlos a una nueva variable).

Una vez que las claves están ordenadas, puede comenzar a usarlas una por una para acceder al contenido del objeto antiguo para llenar un nuevo objeto (que ahora está ordenado).

A continuación se muestra un ejemplo del procedimiento (puede probarlo en sus navegadores específicos):

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

Nota: Object.keys es un método ECMAScript 5.1 pero aquí hay un polyfill para navegadores antiguos:

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

Transferí algunas enumeraciones de Java a objetos javascript.

Estos objetos me devolvieron las matrices correctas. Si las claves de objeto son de tipo mixto (string, int, char), hay un problema.

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

Fragmento simple y legible, usando lodash.

Debe poner la clave entre comillas solo cuando llame a sortBy. No tiene que estar entre comillas en los datos en sí.

_.sortBy(myObj, "key")

Además, su segundo parámetro para asignar es incorrecto. Debería ser una función, pero usar pluck es más fácil.

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

2

Hay un gran proyecto de @sindresorhus llamado sort-keys que funciona de maravilla.

Puedes consultar su código fuente aquí:

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

O puede usarlo con npm:

$ npm install --save sort-keys

Aquí también hay ejemplos de código de su archivo Léame

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

Respuesta de JavaScript puro para ordenar un objeto. Esta es la única respuesta que sé que manejará números negativos. Esta función es para ordenar objetos numéricos.

Ingrese 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;
}

La salida será un objeto ordenado por esos números con nuevas claves que comienzan en 0.


1

Solo para simplificarlo y aclarar la respuesta de Matt Ball

//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

No estoy seguro si esto responde la pregunta, pero esto es lo que necesitaba.

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

Llamado :

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

1

La única línea:

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

1

la mejor manera de hacerlo es

 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 ()

Primero puede convertir su objeto casi como una matriz en una matriz real, y luego usar .reverse ():

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

El espacio vacío al final si causa porque su primer índice es 1 en lugar de 0. Puede quitar el espacio vacío con .length-- o .pop ().

Alternativamente, si desea pedir prestado .reverse y llamarlo sobre el mismo objeto, debe ser un objeto completamente similar a una matriz. Es decir, necesita una propiedad de longitud:

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

Tenga en cuenta que devolverá el mismo objeto objeto completamente similar a una matriz, por lo que no será una matriz real. Luego puede usar eliminar para eliminar la propiedad de longitud.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.