J'essaye de transformer un tableau d'objets sous une forme comme:

const categories = [{
    "category": "Category 1",
    "desc": "Description 1 of the category 1"
  },
  {
    "category": "Category 1",
    "desc": "Description 2 of the category 1"
  }, {
    "category": "Category 2",
    "desc": "Description 1 of the category 2"
  },
  {
    "category": "Category 2",
    "desc": "Description 2 of the category 2"
  },
  {
    "category": "Category 3",
    "desc": "Description 1 of the category 3"
  }, {
    "category": "Category 3",
    "desc": "Description 2 of the category 3"
  }
];

Au formulaire (ensemble de résultats souhaité);

[
  {
    "category": "Category 1",
    "desriptionList": [
      {
        "desc": "Description 1 of the category 1"
      },
      {
        "desc": "Description 2 of the category 1"
      }
    ]
  },
  {
    "category": "Category 2",
    "desriptionList": [
      {
          "error": "Description 1 of the category 2"
      },
      {
          "error": "Description 2 of the category 2"
      },
    ]
  },
   {
    "category": "Category 3",
    "desriptionList": [
      {
          "error": "Description 1 of the category 3"
      },
      {
          "error": "Description 2 of the category 3"
      },
    ]
  }
]

En utilisant la méthode reduce:

const result = categories.reduce((acc, item) => {
  return [{
    ...acc,
    'category': item.category,
    'desriptionList': item.desc
  }]
}, [])

Mais il semble que j'utilise l'accumulateur d'une mauvaise manière et au mauvais endroit parce qu'il y a une sortie bizarre;

[{
  0: {
    0: { ... },
    category: "Category 3",
    desriptionList: "Description 1 of the category 3"
  },
  category: "Category 3",
  desriptionList: "Description 2 of the category 3"
}]

Codepen

0
corry 25 oct. 2020 à 23:39

3 réponses

Meilleure réponse

Puisque vous devez utiliser pour regrouper les desc en catégories, vous utiliserez un objet comme accumulateur. À chaque itération, répartissez l'accumulateur (acc) dans un nouvel objet, et ajoutez le category actuel.

Pour créer ou mettre à jour l'objet de la catégorie, ajoutez le category et répartissez l'instance précédente de la catégorie (undefined est ignoré), ajoutez le desriptionList, et répartissez le desriptionList précédent (ou une solution de secours si aucune), et ajoutez l'élément desc actuel.

Convertissez en un tableau en utilisant Object.values().

const categories = [{"category":"Category 1","desc":"Description 1 of the category 1"},{"category":"Category 1","desc":"Description 2 of the category 1"},{"category":"Category 2","desc":"Description 1 of the category 2"},{"category":"Category 2","desc":"Description 2 of the category 2"},{"category":"Category 3","desc":"Description 1 of the category 3"},{"category":"Category 3","desc":"Description 2 of the category 3"}];

const result = Object.values(categories.reduce((acc, { category, desc }) => ({
  ...acc,
  [category]: {
    ...acc[category],
    category,
    desriptionList: [
      ...(acc[category]?.desriptionList || []),
      { desc }
    ]
  }
}), {}))

console.log(result)

Une autre option consiste à regrouper les catégories dans une carte, puis à convertir la carte en un tableau avec Array.from().

const categories = [{"category":"Category 1","desc":"Description 1 of the category 1"},{"category":"Category 1","desc":"Description 2 of the category 1"},{"category":"Category 2","desc":"Description 1 of the category 2"},{"category":"Category 2","desc":"Description 2 of the category 2"},{"category":"Category 3","desc":"Description 1 of the category 3"},{"category":"Category 3","desc":"Description 2 of the category 3"}];

const result = Array.from(
    categories.reduce((acc, { category, desc }) => {
    if (!acc.has(category)) acc.set(category, []); // initialize the category with an empty array

    acc.get(category).push({ desc }) // push current desc into the array

    return acc;
  }, new Map()), 
  ([category, desriptionList]) => ({ category, desriptionList }) // convert to an array
)

console.log(result)
0
Ori Drori 25 oct. 2020 à 21:04

La condition "! Target.descriptionList.includes (curr)" garantit qu'il n'y a pas de desc en double pour chaque catégorie. N'hésitez pas à le supprimer si vous le trouvez inutile.

const categories = [{
    "category": "Category 1",
    "desc": "Description 1 of the category 1"
  },
  {
    "category": "Category 1",
    "desc": "Description 2 of the category 1"
  }, {
    "category": "Category 2",
    "desc": "Description 1 of the category 2"
  },
  {
    "category": "Category 2",
    "desc": "Description 2 of the category 2"
  },
  {
    "category": "Category 3",
    "desc": "Description 1 of the category 3"
  }, {
    "category": "Category 3",
    "desc": "Description 2 of the category 3"
  }
];

const newArr = categories.reduce((acc, curr) => {
    let target = acc.find(element => element.category === curr.category);

    if (target) {
        if (!target.descriptionList.includes(curr)) {
            delete curr.category;
            target.descriptionList.push(curr);
        }
    } else {
        acc.push({
            category: curr.category,
            descriptionList: [{ desc: curr.desc }]
        })
    }

    return acc
}, []);

console.log('newArr: ' + JSON.stringify(newArr));

Production

newArr: [
  {
    "category": "Category 1",
    "descriptionList": [
      {
        "desc": "Description 1 of the category 1"
      },
      {
        "desc": "Description 2 of the category 1"
      }
    ]
  },
  {
    "category": "Category 2",
    "descriptionList": [
      {
        "desc": "Description 1 of the category 2"
      },
      {
        "desc": "Description 2 of the category 2"
      }
    ]
  },
  {
    "category": "Category 3",
    "descriptionList": [
      {
        "desc": "Description 1 of the category 3"
      },
      {
        "desc": "Description 2 of the category 3"
      }
    ]
  }
]
1
Simon 25 oct. 2020 à 21:31

Restez simple et utilisez Array.reduce () et Array.findIndex pour parcourir chaque objet et décider si ses données doivent être ajoutées à un objet existant dans l'accumulateur ou si un nouvel objet doit être créé et poussé.

const categories=[{category:"Category 1",desc:"Description 1 of the category 1"},{category:"Category 1",desc:"Description 2 of the category 1"},{category:"Category 2",desc:"Description 1 of the category 2"},{category:"Category 2",desc:"Description 2 of the category 2"},{category:"Category 3",desc:"Description 1 of the category 3"},{category:"Category 3",desc:"Description 2 of the category 3"}];

const result = categories.reduce(( acc, cur ) => {
  let idx = acc.findIndex( obj => obj.category === cur.category )
  if( idx > -1 )
  {
    acc[idx].descriptionList.push(cur.desc)
  }
  else
  {
    acc.push( { category: cur.category, descriptionList: [ cur.desc ] } )
  }
  
  return acc
}, [])

console.log(result)
1
symlink 25 oct. 2020 à 21:11