5
votes

comment grouper par un tableau en JavaScript / Jquery

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.


3 commentaires

Une carte n'est pas un tableau


Votre 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.


6 Réponses :


0
votes

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ée de 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.


4 commentaires

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.



3
votes

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


0 commentaires

3
votes

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


0 commentaires

2
votes

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


0 commentaires

3
votes

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


0 commentaires

0
votes

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


0 commentaires