Home > Enterprise >  JS loop through array and group with map
JS loop through array and group with map

Time:11-23

I have array terms:

[
    {
        "label": "programming",
        "id": 6,
        "taxonomy": "category"
    },
    {
        "label": "design",
        "id": 4,
        "taxonomy": "post_tag"
    },
    {
        "label": "css",
        "id": 3,
        "taxonomy": "post_tag"
    },
    {
        "label": "other",
        "id": 8,
        "taxonomy": "category"
    }
]

I am trying to create the following newArray array from array terms:

[
  {
      "taxonomy": "category",
      "ids": [6, 8]
  },
  {
      "taxonomy": "post_tag",
      "ids": [4, 3]
  },
]

I have to take the id from each object in the terms array and add them to the corresponding taxonomy in the array newArray.

I am trying the following:

const taxonomyArray = [];
const newArray = [];

// Loop through original term array and get the taxonomies
terms.forEach( el => {
   taxonomyArray.push( el['taxonomy'] )
});

// Remove duplicate taxonomy values from array taxonomyArray
const uniqueTaxonomyArray = [ ...new Set(taxonomyArray) ];

// Create the new array
uniqueTaxonomyArray.forEach( el => {
    const groupedArray = terms
    .filter( ( { taxonomy } ) => taxonomy === el )
    .map( ( { value, taxonomy } ) => ( {
       taxonomy: el,
       ids: value
    } ) );

    newArray.push( groupedArray );
});

It is giving me:

[
    [
        {
            "taxonomy": "category",
            "ids": 6
        },
        {
            "taxonomy": "category",
            "ids": 8
        }
    ],
    [
        {
            "taxonomy": "post_tag",
            "ids": 4
        },
        {
            "taxonomy": "post_tag",
            "ids": 3
        }
    ]
]

Is there a better way to achieve this?

CodePudding user response:

Array.reduce with Map

const terms = [ { "label": "programming", "id": 6, "taxonomy": "category" }, { "label": "design", "id": 4, "taxonomy": "post_tag" }, { "label": "css", "id": 3, "taxonomy": "post_tag" }, { "label": "other", "id": 8, "taxonomy": "category" }];

const map = terms.reduce((acc, {id, taxonomy}) => {
  if (acc.has(taxonomy)) {
    acc.get(taxonomy).ids.push(id);
  } else {
    acc.set(taxonomy, {taxonomy: taxonomy, ids: [id]});
  }
  return acc;
}, new Map());

const result = [...map.values()];

console.log(result);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

reduce

The reducer walks through the array element-by-element, at each step adding the current array value to the result from the previous step (this result is the running sum of all the previous steps) — until there are no more elements to add.

// Arrow function
reduce((previousValue, currentValue) => { ... } )
reduce((previousValue, currentValue, currentIndex) => { ... } )
reduce((previousValue, currentValue, currentIndex, array) => { ... } )
reduce((previousValue, currentValue, currentIndex, array) => { ... }, initialValue)

// Callback function
reduce(callbackFn)
reduce(callbackFn, initialValue)

// Inline callback function
reduce(function(previousValue, currentValue) { ... })
reduce(function(previousValue, currentValue, currentIndex) { ... })
reduce(function(previousValue, currentValue, currentIndex, array) { ... })
reduce(function(previousValue, currentValue, currentIndex, array) { ... }, initialValue)
  • Related