J'ai un tableau d'objets avec plusieurs paires de valeurs de clé et je dois les trier en fonction de 'updated_at':
[
{
"updated_at" : "2012-01-01T06:25:24Z",
"foo" : "bar"
},
{
"updated_at" : "2012-01-09T11:25:13Z",
"foo" : "bar"
},
{
"updated_at" : "2012-01-05T04:13:24Z",
"foo" : "bar"
}
]
Quel est le moyen le plus efficace de le faire?
Vous pouvez utiliser Array.sort
.
Voici un exemple (non testé):
arr.sort(function(a, b){
var keyA = new Date(a.updated_at),
keyB = new Date(b.updated_at);
// Compare the 2 dates
if(keyA < keyB) return -1;
if(keyA > keyB) return 1;
return 0;
});
J'ai déjà répondu à une question très similaire ici: Fonction simple pour trier un tableau d'objets
Pour cette question, j'ai créé cette petite fonction qui pourrait faire ce que vous voulez:
function sortByKey(array, key) {
return array.sort(function(a, b) {
var x = a[key]; var y = b[key];
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
}
Voici une version légèrement modifiée de La réponse de @David Brainer-Bankers est triée alphabétiquement par chaîne ou numérique par numéro et garantit que les mots commençant par des majuscules ne sont pas triés par dessus des mots commençant par une lettre minuscule (par exemple, " Apple, Early "serait affiché dans cet ordre).
function sortByKey(array, key) {
return array.sort(function(a, b) {
var x = a[key];
var y = b[key];
if (typeof x == "string")
{
x = (""+x).toLowerCase();
}
if (typeof y == "string")
{
y = (""+y).toLowerCase();
}
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
}
La méthode Array.sort () trie les éléments d'un tableau à la place et renvoie le tableau. Soyez prudent avec Array.sort () car ce n'est pas Immuable . Pour le type immuable, utilisez immutable-sort .
Cette méthode consiste à trier le tableau en utilisant votre updated_at
actuel au format ISO. Nous utilisons new Data(iso_string).getTime()
pour convertir l'heure ISO en horodatage Unix. Un timestamp Unix est un nombre sur lequel nous pouvons faire des calculs simples. Nous soustrayons le premier et le deuxième horodatage du résultat; Si le premier horodatage est supérieur à la seconde, le numéro de retour sera positif. Si le deuxième nombre est plus grand que le premier, la valeur de retour sera négative. Si les deux sont identiques, le retour sera zéro. Cela correspond parfaitement aux valeurs de retour requises pour la fonction inline.
Pour ES6 :
arr.sort((a,b) => new Date(a.updated_at).getTime() - new Date(b.updated_at).getTime());
Pour ES5 :
arr.sort(function(a,b){
return new Date(a.updated_at).getTime() - new Date(b.updated_at).getTime();
});
Si vous changez votre updated_at
pour qu'il soit un horodatage Unix, vous pouvez le faire:
Pour ES6 :
arr.sort((a,b) => a.updated_at - b.updated_at);
Pour ES5 :
arr.sort(function(a,b){
return a.updated_at - b.updated_at;
});
Au moment de cet article, les navigateurs modernes ne supportent pas ES6. Pour utiliser ES6 dans les navigateurs modernes, utilisez babel pour transcrire le code en ES5. Attendez-vous à un support du navigateur pour ES6 dans un avenir proche.
Array.sort () doit récupérer une valeur de retour correspondant à l'un des 3 résultats possibles:
Notez que la valeur de retour sur la fonction inline peut être n'importe quel nombre positif ou négatif. Array.Sort () ne se soucie pas de ce que le Le numéro de retour est. Cela ne sert que si la valeur de retour est positive, négatif ou nul.
Pour le tri immuable: (exemple dans ES6)
const sort = require('immutable-sort');
const array = [1, 5, 2, 4, 3];
const sortedArray = sort(array);
Vous pouvez aussi l'écrire de cette façon:
import sort from 'immutable-sort';
const array = [1, 5, 2, 4, 3];
const sortedArray = sort(array);
L'importation à partir de vous est une nouvelle façon d'inclure javascript dans ES6 et donne à votre code une apparence très propre. Mon préféré
Le tri immuable ne mute pas le tableau source mais renvoie un nouveau tableau. L'utilisation de const
est recommandée sur des données immuables.
Utilisez des traits de soulignement js ou lodash,
var arrObj = [
{
"updated_at" : "2012-01-01T06:25:24Z",
"foo" : "bar"
},
{
"updated_at" : "2012-01-09T11:25:13Z",
"foo" : "bar"
},
{
"updated_at" : "2012-01-05T04:13:24Z",
"foo" : "bar"
}
];
arrObj = _.sortBy(arrObj,"updated_at");
_.sortBy()
renvoie un nouveau tableau
référez-vous http://underscorejs.org/#sortBy et lodash docs https://lodash.com/docs#sortBy
J'ai créé une fonction de tri dans TypeScript que nous pouvons utiliser pour rechercher des chaînes, des dates et des nombres dans un tableau d'objets. Il peut également trier sur plusieurs champs.
export type SortType = 'string' | 'number' | 'date';
export type SortingOrder = 'asc' | 'desc';
export interface SortOptions {
sortByKey: string;
sortType?: SortType;
sortingOrder?: SortingOrder;
}
class CustomSorting {
static sortArrayOfObjects(fields: SortOptions[] = [{sortByKey: 'value', sortType: 'string', sortingOrder: 'desc'}]) {
return (a, b) => fields
.map((field) => {
if (!a[field.sortByKey] || !b[field.sortByKey]) {
return 0;
}
const direction = field.sortingOrder === 'asc' ? 1 : -1;
let firstValue;
let secondValue;
if (field.sortType === 'string') {
firstValue = a[field.sortByKey].toUpperCase();
secondValue = b[field.sortByKey].toUpperCase();
} else if (field.sortType === 'number') {
firstValue = parseInt(a[field.sortByKey], 10);
secondValue = parseInt(b[field.sortByKey], 10);
} else if (field.sortType === 'date') {
firstValue = new Date(a[field.sortByKey]);
secondValue = new Date(b[field.sortByKey]);
}
return firstValue > secondValue ? direction : firstValue < secondValue ? -(direction) : 0;
})
.reduce((pos, neg) => pos ? pos : neg, 0);
}
}
}
Usage:
const sortOptions = [{
sortByKey: 'anyKey',
sortType: 'string',
sortingOrder: 'asc',
}];
arrayOfObjects.sort(CustomSorting.sortArrayOfObjects(sortOptions));
Juste une autre manière plusmathématique, de faire la même chose mais plus courte :
arr.sort(function(a, b){
var diff = new Date(a.updated_at) - new Date(b.updated_at);
return diff/(Math.abs(diff)||1);
});
ou dans le style de flèche lambda lisse:
arr.sort((a, b) => {
var diff = new Date(a.updated_at) - new Date(b.updated_at);
return diff/(Math.abs(diff)||1);
});
Cette méthode peut être réalisée avec n'importe quelle entrée numérique
Avec le support ES2015, cela peut être fait par:
foo.sort((a, b) => a.updated_at < b.updated_at ? -1 : 1)
Trier par une date au format ISO peut coûter cher, sauf si vous limitez les clients aux navigateurs les plus récents et les meilleurs, ce qui permet de créer un horodatage correct en analysant la date par la chaîne.
Si vous êtes sûr de votre entrée, et que vous savez ce sera toujours aaaa-mm-jjThh: mm: ss et GMT (Z), vous pouvez extraire les chiffres de chaque membre et les comparer comme des entiers
array.sort(function(a,b){
return a.updated_at.replace(/\D+/g,'')-b.updated_at.replace(/\D+/g,'');
});
Si la date peut être formatée différemment, vous devrez peut-être ajouter quelque chose pour les personnes aux problèmes iso:
Date.fromISO: function(s){
var day, tz,
rx=/^(\d{4}\-\d\d\-\d\d([tT ][\d:\.]*)?)([zZ]|([+\-])(\d\d):(\d\d))?$/,
p= rx.exec(s) || [];
if(p[1]){
day= p[1].split(/\D/).map(function(itm){
return parseInt(itm, 10) || 0;
});
day[1]-= 1;
day= new Date(Date.UTC.apply(Date, day));
if(!day.getDate()) return NaN;
if(p[5]){
tz= (parseInt(p[5], 10)*60);
if(p[6]) tz+= parseInt(p[6], 10);
if(p[4]== '+') tz*= -1;
if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz);
}
return day;
}
return NaN;
}
if(!Array.prototype.map){
Array.prototype.map= function(fun, scope){
var T= this, L= T.length, A= Array(L), i= 0;
if(typeof fun== 'function'){
while(i< L){
if(i in T){
A[i]= fun.call(scope, T[i], i, T);
}
++i;
}
return A;
}
}
}
}
Données importées
[
{
"gameStatus": "1",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-20 11:32:04"
},
{
"gameStatus": "0",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-19 18:08:24"
},
{
"gameStatus": "2",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-19 18:35:40"
},
{
"gameStatus": "0",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-19 10:42:53"
},
{
"gameStatus": "2",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-20 10:54:09"
},
{
"gameStatus": "0",
"userId": "1a2fefb0-5ae2-47eb-82ff-d1b2cc27875a",
"created_at": "2018-12-19 18:46:22"
},
{
"gameStatus": "1",
"userId": "7118ed61-d8d9-4098-a81b-484158806d21",
"created_at": "2018-12-20 10:50:48"
}
]
POUR ordre croissant
arr.sort(function(a, b){
var keyA = new Date(a.updated_at),
keyB = new Date(b.updated_at);
// Compare the 2 dates
if(keyA < keyB) return -1;
if(keyA > keyB) return 1;
return 0;
});
Exemple pour Ordre Asc
[
{
"gameStatus": "0",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-19 10:42:53"
},
{
"gameStatus": "0",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-19 18:08:24"
},
{
"gameStatus": "2",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-19 18:35:40"
},
{
"gameStatus": "0",
"userId": "1a2fefb0-5ae2-47eb-82ff-d1b2cc27875a",
"created_at": "2018-12-19 18:46:22"
},
{
"gameStatus": "1",
"userId": "7118ed61-d8d9-4098-a81b-484158806d21",
"created_at": "2018-12-20 10:50:48"
},
{
"gameStatus": "2",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-20 10:54:09"
},
{
"gameStatus": "1",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-20 11:32:04"
}
]
POUR ordre décroissant
arr.sort(function(a, b){
var keyA = new Date(a.updated_at),
keyB = new Date(b.updated_at);
// Compare the 2 dates
if(keyA > keyB) return -1;
if(keyA < keyB) return 1;
return 0;
});
Exemple pour Desc Order
[
{
"gameStatus": "1",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-20 11:32:04"
},
{
"gameStatus": "2",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-20 10:54:09"
},
{
"gameStatus": "1",
"userId": "7118ed61-d8d9-4098-a81b-484158806d21",
"created_at": "2018-12-20 10:50:48"
},
{
"gameStatus": "0",
"userId": "1a2fefb0-5ae2-47eb-82ff-d1b2cc27875a",
"created_at": "2018-12-19 18:46:22"
},
{
"gameStatus": "2",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-19 18:35:40"
},
{
"gameStatus": "0",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-19 18:08:24"
},
{
"gameStatus": "0",
"userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
"created_at": "2018-12-19 10:42:53"
}
]
Quant à aujourd'hui, réponses de @knowbody ( https://stackoverflow.com/a/42418963/6778546 ) et de @Rocket Hazmat ( https://stackoverflow.com/a/8837511/6778546 ) peuvent être combinés pour assurer la prise en charge ES2015 et le traitement correct des dates:
arr.sort((a, b) => {
const dateA = new Date(a.updated_at);
const dateB = new Date(b.updated_at);
return dateA - dateB;
});
Pour être complet, voici une courte implémentation générique de sortBy:
function sortBy(list, keyFunc) {
return list.sort((a,b) => keyFunc(a) - keyFunc(b));
}
sortBy([{"key": 2}, {"key": 1}], o => o["key"])
Notez que cela utilise la méthode de tri des tableaux qui trie sur place . Pour une copie, vous pouvez utiliser arr.concat () ou arr.slice (0) ou une méthode similaire pour créer une copie.
Array.sort()
pour trier un tableau…
) pour rendre la fonction pureupdated_at
)Array.sort()
fonctionne en soustrayant deux propriétés des éléments actuel et suivant s'il s'agit d'un nombre/objet sur lequel vous pouvez effectuer des opérations arythmiquesconst input = [
{
updated_at: '2012-01-01T06:25:24Z',
foo: 'bar',
},
{
updated_at: '2012-01-09T11:25:13Z',
foo: 'bar',
},
{
updated_at: '2012-01-05T04:13:24Z',
foo: 'bar',
}
];
const sortByUpdatedAt = (items) => [...items].sort((itemA, itemB) => new Date(itemA.updated_at) - new Date(itemB.updated_at));
const output = sortByUpdatedAt(input);
console.log(input);
/*
[ { updated_at: '2012-01-01T06:25:24Z', foo: 'bar' },
{ updated_at: '2012-01-09T11:25:13Z', foo: 'bar' },
{ updated_at: '2012-01-05T04:13:24Z', foo: 'bar' } ]
*/
console.log(output)
/*
[ { updated_at: '2012-01-01T06:25:24Z', foo: 'bar' },
{ updated_at: '2012-01-05T04:13:24Z', foo: 'bar' },
{ updated_at: '2012-01-09T11:25:13Z', foo: 'bar' } ]
*/
var months = [
{
"updated_at" : "2012-01-01T06:25:24Z",
"foo" : "bar"
},
{
"updated_at" : "2012-01-09T11:25:13Z",
"foo" : "bar"
},
{
"updated_at" : "2012-01-05T04:13:24Z",
"foo" : "bar"
}];
months.sort((a, b)=>{
var keyA = new Date(a.updated_at),
keyB = new Date(b.updated_at);
// Compare the 2 dates
if(keyA < keyB) return -1;
if(keyA > keyB) return 1;
return 0;
});
console.log(months);
Avec cela, nous pouvons passer une fonction clé à utiliser pour le tri
Array.prototype.sortBy = function(key_func, reverse=false){
return this.sort( (a, b) => {
var keyA = key_func(a),
keyB = key_func(b);
if(keyA < keyB) return reverse? 1: -1;
if(keyA > keyB) return reverse? -1: 1;
return 0;
});
}
Alors par exemple si nous avons
var arr = [ {date: "01/12/00", balls: {red: "a8", blue: 10}},
{date: "12/13/05", balls: {red: "d6" , blue: 11}},
{date: "03/02/04", balls: {red: "c4" , blue: 15}} ]
Nous pouvons faire
arr.sortBy(el => el.balls.red)
/* would result in
[ {date: "01/12/00", balls: {red: "a8", blue: 10}},
{date: "03/02/04", balls: {red: "c4", blue: 15}},
{date: "12/13/05", balls: {red: "d6", blue: 11}} ]
*/
ou
arr.sortBy(el => new Date(el.date), true) // second argument to reverse it
/* would result in
[ {date: "12/13/05", balls: {red: "d6", blue:11}},
{date: "03/02/04", balls: {red: "c4", blue:15}},
{date: "01/12/00", balls: {red: "a8", blue:10}} ]
*/
ou
arr.sortBy(el => el.balls.blue + parseInt(el.balls.red[1]))
/* would result in
[ {date: "12/13/05", balls: {red: "d6", blue:11}}, // red + blue= 17
{date: "01/12/00", balls: {red: "a8", blue:10}}, // red + blue= 18
{date: "03/02/04", balls: {red: "c4", blue:15}} ] // red + blue= 19
*/
Vous pouvez créer une fermeture et la passer de cette façon voici mon exemple qui fonctionne
$.get('https://data.seattle.gov/resource/3k2p-39jp.json?$limit=10&$where=within_circle(incident_location, 47.594972, -122.331518, 1609.34)',
function(responce) {
var filter = 'event_clearance_group', //sort by key group name
data = responce;
var compare = function (filter) {
return function (a,b) {
var a = a[filter],
b = b[filter];
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
};
};
filter = compare(filter); //set filter
console.log(data.sort(filter));
});