0

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?

1
  • Use flatMap instead of forEach Commented Nov 21, 2021 at 13:36

1 Answer 1

3

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

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)
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! This looks like it is working great. What does acc stand for?
@CyberJ it's accumulative result from each reducing step.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.