Tengo una matriz de objetos JavaScript:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
¿Cómo puedo ordenarlos por el valor de last_nom
en JavaScript?
Lo sé sort(a,b)
, pero eso solo parece funcionar en cadenas y números. ¿Necesito agregar un toString()
método a mis objetos?
javascript
arrays
sorting
Tyrone Slothrop
fuente
fuente
Respuestas:
Es bastante fácil escribir su propia función de comparación:
O en línea (c / o Marco Demaio):
fuente
return a.last_nom.localeCompare(b.last_nom)
funcionará también.return a.value - b.value;
(ASC)localeCompare
es importante cuando se usan caracteres acentuados en idiomas extranjeros, y también es más elegante.También puede crear una función de ordenación dinámica que clasifique los objetos por el valor que pasa:
Entonces puede tener una variedad de objetos como este:
... y funcionará cuando lo hagas:
En realidad, esto ya responde a la pregunta. La parte de abajo está escrita porque muchas personas me contactaron, quejándose de que no funciona con múltiples parámetros .
Parámetros Múltiples
Puede usar la siguiente función para generar funciones de clasificación con múltiples parámetros de clasificación.
Lo que te permitiría hacer algo como esto:
Matriz de subclasificación
Para los afortunados entre nosotros que pueden usar ES6, lo que permite extender los objetos nativos:
Eso permitiría esto:
fuente
dynamicSort()
en el ejemplo anterior colocará letras mayúsculas delante de las minúsculas. Por ejemplo, si tengo los valoresAPd
,Aklin
yAbe
- los resultados en un ASC tipo debe serAbe
,Aklin
,APd
. Sin embargo, con su ejemplo, los resultados sonAPd
,Abe
,Aklin
. De todos modos para corregir este comportamiento?var result = a[property].localeCompare(b[property]);
lugar devar result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
.if( !isNaN(a[property]) ) a[property] = Number(a[property]); if( !isNaN(b[property]) ) b[property] = Number(b[property]);
En ES6 / ES2015 o posterior, puede hacer lo siguiente:
Antes de ES6 / ES2015
fuente
last_nom
usar solo el número en la matriz1
:?objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom, undefined, {numberic: true}));
underscore.js
use subrayado, es pequeño e impresionante ...
fuente
var sortedObjs = _.sortBy( objs, 'first_nom' );
.objs
será no ser clasificado como un resultado de esto. La función devolverá una matriz ordenada. Eso lo haría más explícito.var reverseSortedObjs = _.sortBy( objs, 'first_nom' ).reverse();
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"> </script>
Lodash
para aquellos que prefieren esevar sortedObjs = _.sortBy( objs, 'first_nom' );
o si lo desea en un orden diferente:var sortedObjs = _.orderBy( objs, ['first_nom'],['dsc'] );
No entiendo por qué la gente lo hace tan complicado:
Para motores más estrictos:
Cambie el operador para ordenarlo por orden alfabético inverso.
fuente
if(a.count == b.count) return a.name > b.name; else return a.count > b.count;
Si tiene apellidos duplicados, puede ordenarlos por nombre-
fuente
b
debería aparecer despuésa
en la matriz. Si se devuelve un número positivo, significa quea
debe venir despuésb
. Si0
se devuelve, significa que se consideran iguales. Siempre puede leer la documentación: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…1, 0, -1
antes de preguntar esto aquí. Simplemente no estaba encontrando la información que necesitaba.Solución simple y rápida a este problema utilizando la herencia del prototipo:
Ejemplo / uso
Actualización: ya no modifica la matriz original.
fuente
A partir de 2018 hay una solución mucho más corta y elegante. Solo usa. Array.prototype.sort () .
Ejemplo:
fuente
a.value - b.value
utilizados para comparar los atributos del objeto ( números en este caso) se pueden adoptar para los distintos tiempos de datos. Por ejemplo, regex se puede usar para comparar cada par de cadenas vecinas .Antigua respuesta que no es correcta:
ACTUALIZAR
Del comentario de Beauchamp:
Formato más legible:
Sin ternar anidados:
Explicación:
Number()
lanzarátrue
hacia1
yfalse
hacia0
.fuente
arr.sort((a, b) => a.name < b.name ? -1 : (a.name > b.name ? 1 : 0))
En lugar de utilizar una función de comparación personalizada, también puede crear un tipo de objeto con un
toString()
método personalizado (que es invocado por la función de comparación predeterminada):fuente
Lodash.js (superconjunto de Underscore.js )
Es bueno no agregar un marco para cada lógica simple, pero confiar en marcos de utilidad bien probados puede acelerar el desarrollo y reducir la cantidad de errores.
Lodash produce código muy limpio y promueve un estilo de programación más funcional . En un vistazo, queda claro cuál es la intención del código.
El problema de OP simplemente se puede resolver como:
¿Más información? Por ejemplo, tenemos el siguiente objeto anidado:
Ahora podemos usar la abreviatura _.property
user.age
para especificar la ruta a la propiedad que debe coincidir. Ordenaremos los objetos de usuario por la propiedad de edad anidada. Sí, permite la coincidencia de propiedades anidadas.¿Quieres revertirlo? No hay problema. Use _.reverse .
¿Quieres combinar ambos usando cadena ?
¿O cuándo prefieres el flujo sobre la cadena?
fuente
Puedes usar
La forma más fácil: Lodash
( https://lodash.com/docs/4.17.10#orderBy )
Este método es como _.sortBy, excepto que permite especificar el orden de clasificación de los iterados para ordenar. Si las órdenes no están especificadas, todos los valores se ordenan en orden ascendente. De lo contrario, especifique un orden de "desc" para descendente o "asc" para el orden de clasificación ascendente de los valores correspondientes.
Argumentos
colección (Array | Object): la colección para iterar. [iteratees = [_. identity]] (Array [] | Function [] | Object [] | string []): Los iteratees para ordenar. [pedidos] (cadena []): el orden de los iterados.
Devoluciones
(Matriz): devuelve la nueva matriz ordenada.
fuente
Aquí hay muchas buenas respuestas, pero me gustaría señalar que se pueden extender de manera muy simple para lograr una clasificación mucho más compleja. Lo único que tiene que hacer es usar el operador OR para encadenar funciones de comparación como esta:
Donde
fn1
,fn2
... son las funciones de clasificación que devuelven [-1,0,1]. Esto da como resultado "ordenar por fn1", "ordenar por fn2", que es prácticamente igual a ORDER BY en SQL.Esta solución se basa en el comportamiento del
||
operador que evalúa la primera expresión evaluada que se puede convertir en verdadera .La forma más simple tiene solo una función en línea como esta:
Teniendo dos pasos con
last_nom
, elfirst_nom
orden de clasificación se vería así:Una función de comparación genérica podría ser algo como esto:
Esta función podría ampliarse para admitir campos numéricos, sensibilidad de mayúsculas y minúsculas, tipos de datos arbitrarios, etc.
Puedes usarlos encadenándolos por orden de prioridad:
El punto aquí es que JavaScript puro con enfoque funcional puede llevarlo lejos sin bibliotecas externas o código complejo. También es muy efectivo, ya que no es necesario analizar las cadenas.
fuente
Ejemplo de uso:
Guión:
fuente
1, 0, -1
se utilizan dígitos para ordenar. Incluso con su explicación anterior, que se ve muy bien, todavía no lo entiendo del todo. Siempre pienso-1
en cuando uso la propiedad de longitud de matriz, es decir:arr.length = -1
significa que el elemento no se encuentra. Probablemente estoy mezclando cosas aquí, pero ¿podría ayudarme a entender por qué1, 0, -1
se utilizan los dígitos para determinar el orden? Gracias.a
yb
, sia
es mayor queb
agregue 1 al índice dea
y colóquelo detrásb
, sia
es menor queb
, reste 1 dea
y colóquelo delante deb
. Sia
yb
son iguales, agregue 0 aa
y déjelo donde está.No he visto este enfoque en particular sugerido, así que aquí hay un método de comparación breve que me gusta usar que funciona para ambos
string
ynumber
:Aquí hay una explicación de
sortBy()
:sortBy()
acepta unfn
que selecciona qué valor de un objeto usar como comparación y devuelve una función a la que se puede pasar directamenteArray.prototype.sort()
. En este ejemplo, estamos utilizandoo.last_nom
como valor de comparación, por lo que cada vez que recibimos a través de dos objetosArray.prototype.sort()
tales comoy
usamos
para compararlos
Recordando eso
fn = o => o.last_nom
, podemos expandir la función de comparación al equivalenteEl
||
operador lógico OR tiene una funcionalidad de cortocircuito que es muy útil aquí. Debido a cómo funciona, el cuerpo de la función anterior significaComo una ventaja adicional, aquí está el equivalente en ECMAScript 5 sin funciones de flecha, que desafortunadamente es más detallado:
fuente
Sé que esta pregunta es demasiado antigua, pero no vi ninguna implementación similar a la mía.
Esta versión se basa en el modismo de transformación de Schwartz .
Aquí hay un ejemplo de cómo usarlo:
fuente
Ordenar (más) matrices complejas de objetos
Como probablemente encuentre estructuras de datos más complejas como esta matriz, ampliaría la solución.
TL; DR
Problema
Encontré lo siguiente y no pude cambiarlo. Tampoco quería aplanar el objeto temporalmente. Tampoco quería usar el subrayado / lodash, principalmente por razones de rendimiento y la diversión de implementarlo yo mismo.
Objetivo
El objetivo es ordenarlo principalmente por
People.Name.name
y en segundo lugar porPeople.Name.surname
Los obstáculos
Ahora, en la solución base usa la notación de corchetes para calcular las propiedades para ordenar dinámicamente. Aquí, sin embargo, también tendríamos que construir dinámicamente la notación de corchetes, ya que esperaría que algunos
People['Name.name']
funcionen, lo que no funciona.Simplemente hacer
People['Name']['name']
, por otro lado, es estático y solo te permite bajar el n nivel -ésimo.Solución
La adición principal aquí será caminar por el árbol de objetos y determinar el valor de la última hoja, debe especificar, así como cualquier hoja intermedia.
Ejemplo
Ejemplo de trabajo en JSBin
fuente
Una opción mas:
ordena ascendente por defecto.
fuente
Una función simple que ordena una matriz de objetos por una propiedad
Uso:
fuente
Una manera simple:
Ver que
'.toLowerCase()'
es necesario para evitar errores en la comparación de cadenas.fuente
objs.sort( (a,b) => b.last_nom.toLowerCase() < a.last_nom.toLowerCase() );
parámetros desc adicionales para el código Ege Özcan
fuente
Combinando la solución dinámica de Ege con la idea de Vinay, obtienes una buena solución robusta:
Uso:
fuente
Según su ejemplo, debe ordenar por dos campos (apellido, nombre), en lugar de uno. Puede usar la biblioteca Alasql para hacer este tipo en una línea:
Pruebe este ejemplo en jsFiddle .
fuente
fuente
Dado el ejemplo original:
Ordenar por múltiples campos:
Notas
a.localeCompare(b)
está universalmente compatible y vuelve -1,0,1 sia<b
,a==b
,a>b
respectivamente.||
en la última línea dalast_nom
prioridad sobrefirst_nom
.var age_order = left.age - right.age;
return -last_nom_order || -first_nom_order || -age_order;
fuente
Prueba esto,
fuente
Es posible que deba convertirlos a minúsculas para evitar confusiones.
fuente
fuente
Usando Ramda,
npm instalar ramda
fuente
Este es un problema simple, no sé por qué las personas tienen una solución tan compleja.
Una función de clasificación simple (basada en el algoritmo de clasificación rápida ):
Use ejemplo:
fuente