Utilizing the reduce method to transform an array containing nested arrays into a different structure

I'm having trouble figuring out how to restructure the array below.

I attempted to utilize the reduce function in JavaScript but unfortunately, I couldn't make it work.

So far, this is the function I have come up with:

var comb = []
var setEle = []
var setEle = []
input.forEach(a => {
  a.productVariations.forEach(element => {
    if (comb.indexOf(element.variationName) === -1) {
      comb.push(element.variationName)

      let group = element.variationOptions.reduce((r, a) => {
        r['variationName'] = element.variationName
        r['variationOptions'] = [...(r[a.name] || []), a]

        return r
      }, {})

      group['linked'] = []
      setEle.push(group)
    }
  })

})

How can I reorganize the array as shown below and successfully use my reduce function?

var input = [
  {
    companyName: 'ABC',
    productVariations: [
      {
        variationName: 'Colour',
        variationOptions: [
          {
            name: 'Blue'
          },
          {
            name: 'Red'
          }
        ]
      },
      {
        variationName: 'Pattern',
        variationOptions: [
          {
            name: 'Bold'
          },
          {
            name: 'Spotted'
          }
        ]
      }
    ]
  },
  {
    companyName: 'BBC',
    productVariations: [
      {
        variationName: 'Colour',
        variationOptions: [
          {
            name: 'Blue'
          },
          {
            name: 'Red'
          },
          {
            name: 'Purple '
          }
        ]
      }
    ]
  }
]

This is the desired output format:

var output = [
  {
    variationName: 'Colour',
    variationOptions: [
      {
        name: 'Blue'
      },
      {
        name: 'Purple'
      },
      {
        name: 'Red'
      },
    ],
    linked: [
      {
        companyName: 'BBC'
      },
      {
        companyName: 'ABC'
      }
    ]
  },
  {
    variationName: 'Pattern',
    variationOptions: [
      {
        name: 'Bold'
      },
      {
        name: 'Spotted'
      },
    ],
    linked: [
      {
        companyName: 'ABC',
      }
    ]
  }
]

In the output array, the variationOptions are grouped by variationName and the relevant companyName is added to the linked child array.

Answer №1

To achieve unique items, utilize the forEach method to loop through and construct an object with values from companyNames and variationOptions, stored as a Set. Subsequently, recreate the array by leveraging the map function on the previous sets.

const merge = (arr) => {
  const result = {};
  arr.forEach(({ companyName, productVariations }) => {
    productVariations.forEach(({ variationName, variationOptions }) => {
      if (!result[variationName]) {
        result[variationName] = { options: new Set(), links: new Set() };
      }
      result[variationName].links.add(companyName);
      variationOptions.forEach(({ name }) =>
        result[variationName].options.add(name)
      );
    });
  });
  return Object.entries(result).map(([variationName, {options, links}]) => ({
    variationName,
    variationOptions: [...options].map((name) => ({ name })),
    linked: [...links].map((companyName) => ({ companyName })),
  }));
};

var data = [
  {
    companyName: "ABC",
    productVariations: [
      {
        variationName: "Colour",
        variationOptions: [
          {
            name: "Blue",
          },
          {
            name: "Red",
          },
        ],
      },
      {
        variationName: "Pattern",
        variationOptions: [
          {
            name: "Bold",
          },
          {
            name: "Spotted",
          },
        ],
      },
    ],
  },
  {
    companyName: "BBC",
    productVariations: [
      {
        variationName: "Colour",
        variationOptions: [
          {
            name: "Blue",
          },
          {
            name: "Red",
          },
          {
            name: "Purple ",
          },
        ],
      },
    ],
  },
];

console.log(merge(data));

Answer №2

Here is a solution that can be implemented:


const combineVariations = input.flatMap(obj => obj.productVariations.map(x => ({...x, linked:[{companyName: obj.companyName}]})))
const finalResult = combineVariations.reduce((acc, curr) => {
    const existingObj = acc.find(x => x.variationName === curr.variationName)
    if(existingObj) {
        const uniqueOptions = [...new Set([...curr.variationOptions, ...existingObj.variationOptions].map(x => x.name))]
        existingObj.variationOptions = uniqueOptions.map(x => ({name: x}));
        existingObj.linked.push(...curr.linked)
    } else {
        acc.push(curr)
    }
    return acc;
}, [])

Answer №3

Here is an example:

def process_data(data):
    processed_data = []

    for item in data:
        existing_item = next((x for x in processed_data if x['key'] == item['key']), None)

        if existing_item:
            existing_item['values'].extend(item['values'])
        else:
            processed_data.append({
                'key': item['key'],
                'values': item['values']
            })

    return processed_data

input_data = [
    {'key': 'A', 'values': [1, 2, 3]},
    {'key': 'B', 'values': [4, 5]},
    {'key': 'A', 'values': [6, 7]}
]

output_data = process_data(input_data)
print(output_data)
<pre id="output" />

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error: Browserify jQuery Plugin Not Working

Having trouble browserifying a jQuery plugin and keep seeing this error in the browsers console: Uncaught Error: Cannot find module 'jquery' Here's how I have my package.json set up: "browserify": { "transform": [ "browserify-shim" ...

Guide to sending client-to-client notifications in Angular/Ionic with Firebase Cloud Messaging

I am looking to implement client-client push notifications (not server-to-client). My goal is to send a notification when one user messages another. Is this feasible? How can I achieve this using the structure in the Firebase real-time database? Here is a ...

Can I rely on setTimeout to guarantee the execution of a task in NodeJS?

I am working on a REST backend using ExpressJS. One of the functionalities of this backend is to allow users to upload file assets, but these files should only exist for 10 minutes. Is it secure to rely on setTimeout to automatically delete the uploaded f ...

What is the best way to set up a server-sent-events broadcast feature in totaljs?

Let's imagine this situation: Client1 and Client2 are currently in session1 Meanwhile, Client3 and Client4 are part of session2 My aim now is to send event "a" to all clients in session1 exclusively. I came across this example: https://github ...

What is the best way to retrieve data from an array within an Express application?

Working with the rest API using express ejs in Node.js has brought up an issue. The JSON data received from the API contains an array within an array. Specifically, I am trying to extract the value of the feature_image attribute under guid. However, when ...

display elements in indexed alphabetical order

Is it possible to format the $index output in alphabetical order instead of numerical? <div ng-repeat="name in names">{{$index}}</div> I am wondering if this can be achieved. ...

The type does not contain a property named `sort`

"The error message 'Property sort does not exist on type (and then shoes4men | shoes4women | shoes4kids)' pops up when attempting to use category.sort(). I find it puzzling since I can successfully work with count and add a thousand separato ...

Using Ajax to return a Post type in c# mvc 4 instead of a value

Hey there, I seem to be encountering an issue that I could use some help with. $.ajax({ type: "POST", url: "/controller/CreateList", contentType: "application/json; charset=utf-8", traditional: true, ...

At what point are routed components initialized?

Here is a route setup I am working with: path: ':id', component: ViewBookPageComponent }, After adding this route, an error keeps popping up: Error: Cannot read property 'id' of null I haven't included a null check in the compo ...

How to dynamically insert elements into the HTML page using Angular

When my page first loads, it looks like this <body> <div class="col-md-12" id="dataPanes"> <div class="row dataPane"> Chunk of html elements </div> </div> <div class"col-md-12 text-right"> <input type="butt ...

Achieving the perfect alignment: Centering a paragraph containing an image using JQuery

I need help centering the background image of my <p> tag on the webpage. Script $(function() { $('ul.nav a').bind('click', function(event) { var $anchor = $(this); $('html, body').stop().animate({ ...

Create a lockscreen feature in AngularJS that becomes active after a period of inactivity

I am looking to integrate a lockscreen feature into my app using Angular.js. This lockscreen will consist of a route and an HTML template containing a form that prompts the user to re-enter their password in order to keep their session active. The purpose ...

What is the process for removing a specific row from a datatable?

I have implemented a data-table using Vue and Vuetify. When I click on the delete icon in a specific row, a snackbar pops up with two buttons - yes and no. If I click on the yes button, I want to delete that specific row. How can I achieve this functionali ...

Differentiating Between Arrays and Objects in AngularJS ng-repeat

When using ng-repeat to display data in a View from an endpoint in the form of an atom feed, I encountered an issue. The endpoint returns JSON if the Accept header is 'application/json', but when there is only one entry in the atom response, the ...

Unlock the potential of Stripe's confirmCardSetup method when working with multiple elements in Laravel Cashier integrated with a Vue application. Master

Is it possible to send inputs separately from Stripe using the confirmCardSetup method, even though the documentation only mentions one cardElement element? https://stripe.com/docs/js/setup_intents/confirm_card_setup -> check the official documentation ...

Is it possible to retrieve a single attribute from a parent object using the Fast JSON API within Rails?

I am in the process of developing a travel application that utilizes a backend Rails API. To serialize my data, I have chosen to implement the Fast JSON API. Within my app, there exists a collection of countries, each containing numerous cities and attract ...

Holding off on executing a function until a write stream finishes

I'm currently working on a project that involves fetching multiple JSON files from Google Drive and then converting them into objects within my code. My approach includes using a write stream to create the file locally and then parsing it with JSON.pa ...

Utilizing Selenium Webdriver to efficiently scroll through a webpage with AJAX-loaded content

I am currently utilizing Selenium Webdriver to extract content from a webpage. The challenge I'm facing is that the page dynamically loads more content using AJAX as the user scrolls down. While I can programmatically scroll down using JavaScript, I a ...

When using JavaScript to redirect with window.location, the referrer header is not properly set

Currently, I am attempting to utilize window.location in React to redirect to a third-party page. However, upon making the redirect, the third-party server is not receiving a referrer header from my redirection. Any assistance on resolving this issue wou ...

Encountering an EJS error stating SyntaxError: a closing parenthesis is missing after the argument list in the file path C:Userscomputer pointDesktopproject2viewshome.ejs

Struggling to retrieve data from app.js through ejs and encountering an error. Pursuing a degree in Computer Science <%- include('header'); -%> <h1><%= foo%></h1> <p class = "home-content">It is a fact that readers ...