0
votes

Réduisez le tableau d'objets en clés uniques et ajoutez un tableau de valeurs communes à cette clé

Je voudrais regrouper les valeurs de ce tableau par sa clé de car , puis pousser les valeurs communes à cette voiture dans un tableau de valeurs.

J'ai réussi à le faire avec cela, mais je me demandais s'il y avait un moyen plus simple de le faire avec réduire.

const arr = [{
  car: 'audi',
  value: 'black'
}, {
  car: 'audi',
  value: 'expensive'
}, {
  car: 'fiat',
  value: 'red'
}, {
  car: 'fiat',
  value: 'cheap'
}]

// Simple array with unique car
const cars = Array.from(new Set(arr.map(({ car }) => car)))
// Array of objects with unique `car` and an empty `values` array for each
const result = cars.map((car) => ({ car, values: [] }))

// Push to values array the `value` for each car
arr.map((obj) => {
  result.map((res) => {
    if (obj.car === res.car) {
      res.values.push(obj.value)
    }
  })
})

console.log(result)
/*
[{
  car: 'audi',
  values: ['black', 'expensive']
}, {
  car: 'fiat',
  values: ['red', 'cheap']
}]
*/


0 commentaires

3 Réponses :


2
votes

Créez un objet indexé par le nom de la car , puis itérez sur le tableau d'origine, en poussant la valeur vers le tableau sur l'objet:

const arr = [{
  car: 'audi',
  value: 'black'
}, {
  car: 'audi',
  value: 'expensive'
}, {
  car: 'fiat',
  value: 'red'
}, {
  car: 'fiat',
  value: 'cheap'
}];

const carsByName = arr.reduce((a, { car, value }) => {
  if (!a[car]) a[car] = { car, value: [] };
  a[car].value.push(value);
  return a;
}, {});
console.log(Object.values(carsByName));

Bien que cela puisse être fait avec reduce , ce n'est sans doute pas très approprié du point de vue sémantique lorsque l'accumulateur ne change jamais (et est un peu bruyant, syntaxiquement):

const arr = [{
  car: 'audi',
  value: 'black'
}, {
  car: 'audi',
  value: 'expensive'
}, {
  car: 'fiat',
  value: 'red'
}, {
  car: 'fiat',
  value: 'cheap'
}];

const carsByName = {};
for (const { car, value } of arr) {
  if (!carsByName[car]) carsByName[car] = { car, value: [] };
  carsByName[car].value.push(value);
}
console.log(Object.values(carsByName));


3 commentaires

Merci, ça a l'air génial, puis-je faire [carsByName] au lieu d'Object.values (carsByName)?


Cela vous donnerait un tableau contenant un seul objet, cet objet étant indexé par nom de voiture. Si cette structure de données est ce que vous voulez, allez-y, mais ce n'est pas ce que votre résultat attendu dans la question était.


Vous avez raison, merci beaucoup pour le code fonctionne très bien



1
votes

Vous pouvez utiliser .reduce pour regrouper les éléments par car , puis, .map pour créer une liste d'objets ayant une car et ses values :

const arr = [{
  car: 'audi',
  value: 'black'
}, {
  car: 'audi',
  value: 'expensive'
}, {
  car: 'fiat',
  value: 'red'
}, {
  car: 'fiat',
  value: 'cheap'
}]

let result = arr.reduce((acc,item) => {
  const values = acc[item.car];
  acc[item.car] = values ? [...values, item.value] : [item.value];
  return acc;
}, {});

result = Object.entries(result).map(([car, values]) => ({car,values}));

console.log(result)


0 commentaires

1
votes

Utilisez simplement réduire pour cela. Gardez au acc la gamme de voitures avec clé car et values . Et puis cartographiez-le. Je veux dire:

const arr = [
  {
    car: "audi",
    value: "black",
  },
  {
    car: "audi",
    value: "expensive",
  },
  {
    car: "fiat",
    value: "red",
  },
  {
    car: "fiat",
    value: "cheap",
  },
];

const result = Object.entries(
  arr.reduce((acc, { car, value }) => {
    if (acc[car]) {
      return {
        ...acc,
        [car]: [...acc[car], value],
      };
    }

    return { ...acc, [car]: [value] };
  }, [])
).map(([car, values]) => ({ car, values }));

console.log(result);


0 commentaires