butbut
butbut

Reputation: 31

How to restructure an array base on an value inside the original array in node js

I am trying to restructure an array. Instead of variant_id at the top, i would like to make collection_id to the top. if the collection_id is the same they should be in the same array. I try using foreach but seems didn't work.

[
  {
    variant_id: '39264031277264',
    collection: [
      {
        collection_id: '260687954128',
        value: true
      }
    ]
  },
  {
    variant_id: '39264022134992',
    collection: [
      {
        collection_id: '260687954128',
        value: true
      }
    ]
  },
  {
    variant_id: '40460795642064',
    collection: [
      {
        collection_id: '277033681104',
        value: true
      }
    ]
  }
]

This is the expected result

[
   {
      "collection_id":"260687954128",
      "variant_id":[
         "39264031277264",
         "39264022134992"
      ]
   },
   {
      "collection_id":"277033681104",
      "variant_id":[
         "40460795642064"
      ]
   }
]

Upvotes: 1

Views: 80

Answers (2)

jsN00b
jsN00b

Reputation: 3691

The below solution may be one possible way to achieve the desired objective.

It uses the following JavaScript concepts/features/ideas:

  1. Object.values
  2. Array.reduce()
  3. De-structuring
  4. ... spread operator
  5. ?. optional chaining operator
  6. ?? nullish coalescing operator
  7. Implicit return

Code Snippet

const reGroupUsingCollectionId = arr => (
  Object.values(                            // extract only the 'values' of resulting object
    arr.reduce(                             // use .reduce() to iterate the array
      (acc, itm) => (                       // 'acc' is the accumulator & 'itm' is current element
        itm.collection.reduce(              // use .reduce() to iterate over 'collection' array
          (fin, {collection_id}) => ({      // 'fin' is the inner-reduce's accumulator
            ...fin,                         // collection_id is de-structured from iterator
            [collection_id]: {
              collection_id,
              variant_id: [                 // populate the variant_id array
                ...(                        // 
                  fin[collection_id]        // use existing variant_id array if collection_id
                  ?.variant_id              // already added to accumulator (fin)
                  ?? []                     // nullish coalescing as empty
                ),
                itm.variant_id              // append itm.variant_id to variant_id array
              ]
            }
          }),
          {...acc}                          // initialize 'fin' to be 'acc'
        )
      ),
      {}                                    // initialize 'acc' to be empty object
    )
  )
);

const data = [{
    variant_id: '39264031277264',
    collection: [{
      collection_id: '260687954128',
      value: true
    }]
  }, {
    variant_id: '39264022134992',
    collection: [{
      collection_id: '260687954128',
      value: true
    }]
  }, {
    variant_id: '40460795642064',
    collection: [{
      collection_id: '277033681104',
      value: true
    }]
  }
];

console.log(reGroupUsingCollectionId(data));

Explanation

Inline comments provide detailed description of each significant step.

Upvotes: 0

eol
eol

Reputation: 24565

You can define a simple mapping function that collects all collection_ids and keeps track of the respective variant_ids:

    const data = [{
        variant_id: '39264031277264',
        collection: [{collection_id: '260687954128', value: true}]
    }, {
        variant_id: '39264022134992',
        collection: [{collection_id: '260687954128', value: true}]
    }, {variant_id: '40460795642064', collection: [{collection_id: '277033681104', value: true}]}
    
    ];
    
function mapData(input) {
  const collections = {};
  for (const variant of input) {
    for (const collection of variant.collection) {
        collections[collection.collection_id] = collections[collection.collection_id] ?? [];
        collections[collection.collection_id].push(variant.variant_id);
    }
  }
  return Object
    .entries(collections)
    .map(([key, value]) => ({collection_id: key, variant_id: value}));
}

console.log(mapData(data));

Upvotes: 2

Related Questions