J'ai un tableau comme ci-dessous
function groupBy(list, keyGetter) {
const map = new Map();
list.forEach((item) => {
const key = keyGetter(item);
if (!map.has(key)) {
map.set(key, [item]);
} else {
map.get(key).push(item);
}
});
return map;
}
const grouped = groupBy(array1, arr => arr.location);
console.log(grouped);
Je veux formater mon tableau comme ci-dessous
array2= [{
location: "CENTRAL",
January: 94,
February: 97,
March: 93},
{
location: "NORTH",
January: 95,
February: 91,
March: 98}];
J'ai essayé d'utiliser group par fonction comme ci-dessous
array1 = [{"month":"January","location":"CENTRAL","percentage":94},
{"month":"February","location":"CENTRAL","percentage":97},
{"month":"March","location":"CENTRAL","percentage":93},
{"month":"January","location":"NORTH","percentage":95},
{"month":"February","location":"NORTH","percentage":91},
{"month":"March","location":"NORTH","percentage":98}];
mais je n'obtiens pas le même format. Des suggestions s'il vous plaît ce qui me manque dans mon idée? Merci beaucoup.
6 Réponses :
Le problème est que vous ne pouvez pas simplement réorganiser les propriétés d'un objet. Selon le Spécifications ECMAScript :
Un objet ECMAScript est une collection
non ordonnéede propriétés^
Vous pouvez réorganiser les propriétés à l'aide de votre fonction, mais l'ordre ne sera pas garanti dans l'objet final.
Je sais que c'est ce qu'ils font mais je doute que ce soit ce qu'ils recherchent.
Désolé @ChiefTwoPencils, mais oui, c'est la seule différence entre leurs deux tableaux - l'ordre des propriétés de chaque objet.
Les accessoires de l'objet sont en fait différents. Par exemple, ils ont des accessoires de mois explicites dans le second plutôt qu'un seul accessoire de mois dans le premier.
Oups, j'ai raté ça.
Vous pouvez en effet utiliser une carte indexée par emplacement, mais avec des objets simples comme valeurs. Le problème dans votre code est que vous poussez les éléments dans un tableau et que vous ne transformez pas les valeurs du mois en propriétés d'un objet singulier (par emplacement).
Donc, étant donné une carte avec des objets simples , itérez l'entrée et injectez les propriétés du mois dans ces objets simples, avec les valeurs de pourcentage correspondantes, puis prenez les valeurs de cette carte:
const array1 = [{"month":"January","location":"CENTRAL","percentage":94},{"month":"February","location":"CENTRAL","percentage":97},{"month":"March","location":"CENTRAL","percentage":93},{"month":"January","location":"NORTH","percentage":95},{"month":"February","location":"NORTH","percentage":91},{"month":"March","location":"NORTH","percentage":98}];
const map = new Map(array1.map(({location}) => [location, { location }]));
array1.forEach(o => map.get(o.location)[o.month] = o.percentage);
const result = [...map.values()];
console.log(result);
Vous pouvez utiliser une approche dynamique en remettant la clé de groupe, les clés pour la clé et la valeur pour la collecte.
Ensuite, ajoutez toutes les paires clé / valeur à l'objet et retournez plus tard les valeurs de la carte. p >
.as-console-wrapper { max-height: 100% !important; top: 0; }
function groupBy(list, group, key, value) {
return Array.from(list
.reduce((map, object) => map.set(object[group], Object.assign(
map.get(object[group]) || { [group]: object[group] },
{ [object[key]]: object[value] }
)), new Map)
.values()
);
}
var array = [{ month: "January", location: "CENTRAL", percentage: 94 }, { month: "February", location: "CENTRAL", percentage: 97 }, { month: "March", location: "CENTRAL", percentage: 93 }, { month: "January", location: "NORTH", percentage: 95 }, { month: "February", location: "NORTH", percentage: 91 }, { month: "March", location: "NORTH", percentage: 98 }],
result = groupBy(array, 'location', 'month', 'percentage');
console.log(result);
Une approche consiste à utiliser .filter () et .map()
var array1 = [{"month":"January","location":"CENTRAL","percentage":94},
{"month":"February","location":"CENTRAL","percentage":97},
{"month":"March","location":"CENTRAL","percentage":93},
{"month":"January","location":"NORTH","percentage":95},
{"month":"February","location":"NORTH","percentage":91},
{"month":"March","location":"NORTH","percentage":98}];
const groupBy = (arr, prop, propName1, propName2, propName3) =>
Object.assign({[prop]:propName1}
, ...arr.filter(({[prop]:p}) => p === propName1)
.map(({[propName2]:m, [propName3]:p}) => ({[m]: p}))
);
const locations = ["CENTRAL", "NORTH"];
let res = locations.map(prop => groupBy(array1, "location", prop, "month", "percentage"));
console.log(res);
Une alternative est d'utiliser la fonction réduire pour regrouper par emplacement et la fonction Object.values pour extraire les objets groupés.
.as-console-wrapper { max-height: 100% !important; top: 0; }
let array1 = [{"month":"January","location":"CENTRAL","percentage":94},{"month":"February","location":"CENTRAL","percentage":97},{"month":"March","location":"CENTRAL","percentage":93},{"month":"January","location":"NORTH","percentage":95},{"month":"February","location":"NORTH","percentage":91},{"month":"March","location":"NORTH","percentage":98}],
groupBy = (array, keygetter) => {
return Object.values(array1.reduce((a, {month, percentage, ...rest}) => {
let key = keygetter(rest);
(a[key] || (a[key] = {location: key}))[month] = percentage;
return a;
}, Object.create(null)));
},
result = groupBy(array1, (o) => o.location);
console.log(result);
Voici un autre exemple utilisant la réduction, transmettez la fonction de rappel et spécifiez la clé qu'elle contient
array1 = [{
"month": "January",
"location": "CENTRAL",
"percentage": 94
},
{
"month": "February",
"location": "CENTRAL",
"percentage": 97
},
{
"month": "March",
"location": "CENTRAL",
"percentage": 93
},
{
"month": "January",
"location": "NORTH",
"percentage": 95
},
{
"month": "February",
"location": "NORTH",
"percentage": 91
},
{
"month": "March",
"location": "NORTH",
"percentage": 98
}
];
function groupBy(list, callback) {
return list.reduce((acc, x) => {
const key = callback(x);
if (!acc[key]) {
return {
...acc,
[key]: [x]
}
}
return {
...acc,
[key]: [...acc[key], x]
}
}, {})
}
// callback function
function locationName(obj) {
return obj.location
}
console.log('group by location name:', groupBy(array1, locationName));
Une
carten'est pas untableauVotre fonction est trop basique pour ce que vous attendez, je suppose. Vous n'indiquez pas comment vous prévoyez d'agréger les valeurs mensuelles. Vous retournez également les données mappées par emplacement, mais vous attendez un tableau simple.
L'ordre ne peut pas être garanti dans un objet.