Add values to an array using the reduce function

My array consists of multiple objects:

const items = [{ search_type: 'environment',
    search_code: 'TBA_ENVIRONMENT00002',
    asset_code: 'ASSET00002' },
  { search_type: 'job',
    search_code: 'TBA_JOB00002',
    asset_code: 'ASSET00002' },
  { search_type: 'environment',
    search_code: 'TBA_ENVIRONMENT00002',
    asset_code: 'ASSET00004' },
  { search_type: 'job',
    search_code: 'TBA_JOB00002',
    asset_code: 'ASSET00004' },
  { search_type: 'job',
    search_code: 'TBA_JOB00003',
    asset_code: 'ASSET00004' },
  { search_type: 'scene',
    search_code: 'TBA_SCENE00006',
    asset_code: 'ASSET00002' },
 ];

I wish to transform it into a structure like this:

{
ASSET00002: {
   environment:["TBA_ENVIRONMENT00002"],
   job:["TBA_JOB00002"],
   scene:["TBA_SCENE00006"]
},
ASSET00004: {
   environment:["TBA_ENVIRONMENT00002"],
   job:["TBA_JOB00002","TBA_JOB00003"]
},
}

Using the following Reduce function logic:

const result = items.reduce((acc, item) => {
  const { search_type, search_code, asset_code } = item;
  return {
    ...acc,
    [asset_code]: {
      ...acc[asset_code], [search_type]: [search_code]
    },
  };
}, {});

The outcome I'm currently getting is:

{
ASSET00002: {
   environment:["TBA_ENVIRONMENT00002"],
   job:["TBA_JOB00002"],
   scene:["TBA_SCENE00006"]
},
ASSET00004: {
   environment:["TBA_ENVIRONMENT00002"],
   job:["TBA_JOB00003"]
},
}

Based on "ASSET00004"-> "job", I expect an array with two values but only receiving one. I'm aware there may be missing elements in my code, struggling to figure out how to properly add values to the array. Appreciate any assistance provided.

Answer №1

If you want to achieve this in a straightforward way, simply use the reduce method and ensure that you append to any existing array while looping through the objects:

const items = [{ search_type: 'environment',
    search_code: 'TBA_ENVIRONMENT00002',
    asset_code: 'ASSET00002' },
  { search_type: 'job',
    search_code: 'TBA_JOB00002',
    asset_code: 'ASSET00002' },
  { search_type: 'environment',
    search_code: 'TBA_ENVIRONMENT00002',
    asset_code: 'ASSET00004' },
  { search_type: 'job',
    search_code: 'TBA_JOB00002',
    asset_code: 'ASSET00004' },
  { search_type: 'job',
    search_code: 'TBA_JOB00003',
    asset_code: 'ASSET00004' },
  { search_type: 'scene',
    search_code: 'TBA_SCENE00006',
    asset_code: 'ASSET00002' },
 ];

const assets = items.reduce((acc, el) => {
  if (!acc[el.asset_code]) {
    acc[el.asset_code] = {};
  }
  acc[el.asset_code][el.search_type] = 
    [...acc[el.asset_code][el.search_type] || [], el.search_code];
  return acc;
}, {});

console.log(assets);

Answer №2

The issue arises due to the following line of code:

[asset_code]: {
 ...acc[asset_code], [search_type]: [search_code]
},

This causes the loss of context for previously stored values in the search_type array, only retaining the most recent value pushed to it.

To address this, we need to check if the array key already exists in the object. If it does not, create a new array; if it does, append the value to the existing one.

The code can be updated as follows:

const result = items.reduce((acc, item, i) => {
  const { search_type, search_code, asset_code } = item;
  return {
    ...acc,
    [asset_code]: {
      ...acc[asset_code],
      [search_type]: acc[asset_code] && acc[asset_code][search_type] ?
       acc[asset_code][search_type].concat([search_code]) : [search_code]
    }
  };
}, {});

In the revised code above, we check if the values are already present in the array and concatenate them if they exist.

Answer №3

It seems like the search_type key is left untouched in your code.

Below is a method using spread operators to extend the array.

const items = [{ search_type: 'environment',
    search_code: 'TBA_ENVIRONMENT00002',
    asset_code: 'ASSET00002' },
  { search_type: 'job',
    search_code: 'TBA_JOB00002',
    asset_code: 'ASSET00002' },
  { search_type: 'environment',
    search_code: 'TBA_ENVIRONMENT00002',
    asset_code: 'ASSET00004' },
  { search_type: 'job',
    search_code: 'TBA_JOB00002',
    asset_code: 'ASSET00004' },
  { search_type: 'job',
    search_code: 'TBA_JOB00003',
    asset_code: 'ASSET00004' },
  { search_type: 'scene',
    search_code: 'TBA_SCENE00006',
    asset_code: 'ASSET00002' },
 ];
/*

{
ASSET00002: {
   environment:["TBA_ENVIRONMENT00002"],
   job:["TBA_JOB00002"],
   scene:["TBA_SCENE00006"]
},
ASSET00004: {
   environment:["TBA_ENVIRONMENT00002"],
   job:["TBA_JOB00002","TBA_JOB00003"]
},
}*/

const res = items.reduce((acc, {asset_code, search_type, search_code}) => ({
  ...acc,
  [asset_code]: {
    ...acc[asset_code],
    [search_type]: [
      // You can include new elements into the array here, but duplicates may occur
      ...(acc[asset_code] && acc[asset_code][search_type] || []),
      search_code
    ] 
  }
}), {})

console.log(res)

Answer №4

Using traditional JavaScript instead of ES6.

const elements = [{ elem_type: 'water',
    elem_code: 'TBA_WATER00002',
    asset_code: 'ASSET00002' },
  { elem_type: 'fire',
    elem_code: 'TBA_FIRE00002',
    asset_code: 'ASSET00002' },
  { elem_type: 'earth',
    elem_code: 'TBA_EARTH00002',
    asset_code: 'ASSET00004' },
  { elem_type: 'wind',
    elem_code: 'TBA_WIND00002',
    asset_code: 'ASSET00004' },
  { elem_type: 'fire',
    elem_code: 'TBA_FIRE00003',
    asset_code: 'ASSET00004' },
  { elem_type: 'air',
    elem_code: 'TBA_AIR00006',
    asset_code: 'ASSET00002' },
 ];


  var output = {};
   elements.forEach( function (elem) {            
      output[elem.asset_code]  = output[elem.asset_code] || {};
      if(output[elem.asset_code][elem.elem_type]){
        output[elem.asset_code][elem.elem_type].push(elem.elem_code);
      }else{
        output[elem.asset_code][elem.elem_type] = new Array(elem.elem_code)
      }
   });

   console.log(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

Animate an image to the right when clicked, then return it to the left with a second click

Seeking help with animating a set of images to move individually 300px right on first click, and then 300px left when clicked again. I'm currently facing an issue where my code is not working. It could be due to A) syntax errors or B) the images not ...

Parameterized function call on click event

There is a function defined as follows: menu[0].onclick = function() { filters.reset_all(); clients.get(); } This function gets called when the user clicks on the first menu element. Now, I need to invoke this function from another place and here ...

Is it possible to pass the chart type as a property when using vue-chart.js?

Is it possible to pass the chart type as a property with vue-chart.js? I would love to see some example source code. Can you please provide guidance on this? ...

Why does the header still show content-type as text/plain even after being set to application/json?

When using fetch() to send JSON data, my code looks like this: var data = { name: this.state.name, password: this.state.password } fetch('http://localhost:3001/register/paitent', { method: 'POST&a ...

Error: Cannot execute 'x' as a function

I am currently developing an Express web application that initiates JavaScript scraping code upon the page's initial load. Below is the node web scraping code (scrape.js): const request = require('request-promise'); const cheerio = require( ...

generate an array composed of promises to be used with Promise.all

Currently, I am working with an array of file paths and my goal is to read all the files inside a Promise.all function, followed by carrying out several tasks. var files = ["./file1.txt", "./file2.txt"] Promise.all(files.forEach(file=>{ /* read file ...

React and Rails are not playing nice when it comes to AJAX POST requests - all

I'm currently facing an issue while setting up this AJAX POST request in my react component to interact with my rails api controller. The browser console shows a 404 error and I am unable to trigger the pry debugger. react/src/pages/HomeIndex.js ge ...

What is the best way to implement a CSS transition for styles that are dynamically created by React?

I have a situation where I am using a button component that is styled based on a theme provided by a context: The code in Button.js looks like: () => { const theme = useContext(themeContext); // { primaryColor: "blue" } return <button className ...

Using JQuery to Iterate Through All Form Inputs

I am attempting to retrieve the values of all input fields from a form using JQuery and store them in an array to be sent via AJAX with a GET request. My initial approach did not yield the desired results: function gatherFormData(){ $('#formId i ...

How can the Flickr API be utilized with JavaScript functions?

In preparation for a project, we are required to utilize the Flickr API in order to display a collection of photos when a specific category is selected. I have successfully set up my categories on the left side of a flexbox container. However, I am struggl ...

Incorporate a genre twist in animated films

Is there a way to implement an animated feature where the letters appear one by one in between a sentence, similar to what is seen on this page? On the linked page, there is a sentence displayed inside a banner that reads: Create meaningful documents Cr ...

Construct object in JavaScript recursively

My current project involves creating a file structure index using nodeJS. I am utilizing the fs.readir function to iterate through files and it is working smoothly. However, I am facing an issue when it comes to descending into the directory structure and ...

create a JavaScript array variable for posting items

My goal is to use this javascript to make four posts for the 'var msg' array. However, it currently posts 'encodeURIComponent(msg[i])' four times instead. How can I resolve this issue? var msg = ['one', 'two& ...

Utilize JavaScript to extract content from a text file and showcase it in a Bootstrap modal pop-up through knockout binding

I'm currently working on a function that reads data from a .txt file (located in the website's root directory) and then displays it in a modal dialog box. I believe I've made progress as the file is recognized during debugging, but unfortuna ...

What is the best way to send an array to an ejs template within an express application?

I've been attempting to pass an array of objects to EJS views in Express, but I'm encountering issues. Here's what I have on the server side: var roominfo = function(roomname){ this.roomname=roomname; }; room_info_array= new Array(1); roo ...

Unable to hide the mobile menu button

https://i.sstatic.net/5rdYY.pngI am currently working on a fun website project . I am facing an issue with the mobile menu button not disappearing using display:none in Safari on my iPhone when in landscape mode, even though it works fine in Chrome. My g ...

I noticed that while my shareService is effectively sending values in Angular 2, I encounter an issue where my other components are displaying default values instead

I'm in the process of developing an application using angular 2. I have a UserService that sends a value to other components indicating whether a user is logged in or not, and it's working correctly in terms of data transmission. The issue I&apos ...

Is onMouseLeave failing to trigger upon exiting an element?

Having an issue with the onMouseLeave event in React. It seems to be triggering when hovering over other elements like the navbar or console, but not when leaving the intended element. function GameCard({name, about, image}) { const [active, ...

Determine the presence of a JSON Value/Array in a web application using JavaScript and visualize the information in a dynamic

Utilizing the Ticketmaster API has provided me with a sample dataset from their platform, Data 1 - Including information on "presales." "sales": { "public": { "startDateTime": "2019-11 ...

Issue an alert and refresh the webpage when a file extension upload script is detected

Here is the JavaScript code I'm using to restrict the file type extension during uploads: function TestFileType( fileName, fileTypes ) { if (!fileName) return; dots = fileName.split(".") //get the part AFTER the LAST period. fileType = "." + dots[do ...