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' }
vdh_ant
fuente
3
posible duplicado de Ordenar un objeto JSON en Javascript
abraham
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.

Mathias Bynens
fuente
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 .

Matt Ball
fuente
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.

nombre clave-
fuente
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

Megajin
fuente
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;
};
Ashit Vora
fuente
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())
Ben
fuente
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), {} ));

sravan ganji
fuente
¿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.

Sergio Moura
fuente
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.

Brian M. Hunt
fuente
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})
Serg
fuente
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]})
Flavien Volken
fuente
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,
});
usuario3286817
fuente
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;
  }, {});
};
Dmitry Sheiko
fuente
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!'
            }
        },
    ]
});
usuario3286817
fuente
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' ] ]
Steven Keith
fuente
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 ...

BlueRaja - Danny Pflughoeft
fuente
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í

Narayanaperumal Gurusamy
fuente
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}
Brunettdan
fuente
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]})
    , {}
)
Martillo Salvaje
fuente
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;
    }, {});
}
Alan Hape
fuente
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;
};
Phani Reddy
fuente
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;
  };
}
Benny Neugebauer
fuente
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"]
Sherali Turdiyev
fuente
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");
JLavoie
fuente
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}
fernandopasik
fuente
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.

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

João Pimentel Ferreira
fuente
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) { ... } ) 
mmm
fuente
1

La única línea:

Object.entries(unordered)
  .sort(([keyA], [keyB]) => keyA > keyB)
  .reduce((obj, [key,value]) => Object.assign(obj, {[key]: value}), {})
metakungfu
fuente
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.

Pedro JR
fuente