Adding data from one object to another in Javascript results in duplicated entries

Despite my efforts to find a solution for my issue, I couldn't locate a relevant topic. Being new to Javascript, I suspect my lack of understanding is hindering me from resolving the problem. After days of trying, I'm still unable to grasp it. Any help would be greatly appreciated - thank you.

Issue: I am attempting to map data from a JSON object retrieved from an API (Source) to a different data structure (Result). Strangely, duplicates are being generated in my assignment, even though I believe I am explicitly assigning to only one position in the data object.

I apologize for the lengthy code example, but the problem lies at the very end of it. In the debugger, I can observe that in each iteration of the loop, all values are assigned to all result series.data - despite not understanding why.

Below is my code:


function Sample(){

    // Source data from the API simplified
    var SourceData = {
        "hits": 4,
        "job": [
            {
                "status": "FINISHED",
                "type": "IMPORT",
            },
            {
                "status": "FAILED",
                "type": "EXPORT",
            },
            {
                "status": "RUNNING",
                "type": "TRANSCODE",
            },
            {
                "status": "FINISHED",
                "type": "TRANSCODE",
            }
        ]
    };

    // Helper variable
    var status = [];


    //Initialize Result data object
    var ResultData = {
    labels: [],
    series: []
    };

    // Used to to extend the Result Data Object later
    var placeholderSeries = {name:'', data: []}

    // Get job types and Status from SourceData and write as labels and series.name to result object without duplicates 
    for (var i=0; i < SourceData.job.length; i++){

        var typeExists = ResultData.labels.indexOf(SourceData.job[i].type);
        var statusExists = status.indexOf(SourceData.job[i].status);

        if (typeExists == -1){
        ResultData.labels.push(SourceData.job[i].type);
        ResultData.labels.sort();
        }

        if (statusExists == -1){

        // Fill array with Status values without duplicates
        status.push(SourceData.job[i].status);
        // Fill result data with empty sub structure
        ResultData.series.push(placeholderSeries);
        }
    }

  // Write a series name for each job status corresponding with the status values of the source
 for(var i=0; i < ResultData.series.length; i++)
  {
      // THIS LINE DOESN'T WORK AS I WOULD EXPECT
      ResultData.series[i].name = status[i]; 
   }
   console.log(JSON.stringify(ResultData,null,4));
}  

The Outcome I get is:


{
    "labels": [
        "EXPORT",
        "IMPORT",
        "TRANSCODE"
    ],
    "series": [
        {
            "name": "RUNNING",
            "data": []
        },
        {
            "name": "RUNNING",
            "data": []
        },
        {
            "name": "RUNNING",
            "data": []
        }
    ]
}

The Expected Outcome should be:

{
    "labels": [
        "EXPORT",
        "IMPORT",
        "TRANSCODE"
    ],
    "series": [
        {
            "name": "FINISH",
            "data": []
        },
        {
            "name": "FAILED",
            "data": []
        },
        {
            "name": "RUNNING",
            "data": []
        }
    ]
} 

Answer №1

function Sample() {
        // Data obtained from simplified API source
        var SourceData = {
            hits: 4,
            job: [
                {
                    status: "FINISHED",
                    type: "IMPORT"
                },
                {
                    status: "FAILED",
                    type: "EXPORT"
                },
                {
                    status: "RUNNING",
                    type: "TRANSCODE"
                },
                {
                    status: "FINISHED",
                    type: "TRANSCODE"
                }
            ]
        };

        // Helper variable to store unique statuses
        var status = [];

        //Initialize Result data object structure
        var ResultData = {
            labels: [],
            series: []
        };


        // Extract job types and Status from SourceData and organize as labels and series.name in result object without duplicates
        for (var i = 0; i < SourceData.job.length; i++) {
            var typeExists = ResultData.labels.indexOf(SourceData.job[i].type);
            var statusExists = status.indexOf(SourceData.job[i].status);
            
            if (typeExists == -1) {
                ResultData.labels.push(SourceData.job[i].type);
                ResultData.labels.sort();
            }

            if (statusExists == -1) {
                // Populate array with unique Status values
                status.push(SourceData.job[i].status);
                // Build empty sub structure in result data 
                var placeholderSeries = { name: "", data: [] };
                ResultData.series.push(placeholderSeries);
            }
        }

        // Assign a series name for each job status based on the status values from the source
        for (var i = 0; i < ResultData.series.length; i++) {
            // CORRECTION NEEDED HERE
            ResultData.series[i].name = status[i];
        }
        console.log(JSON.stringify(ResultData, null, 4));
    }
    Sample();

You have incorrectly utilized reference type. You have duplicated the same placeholderSeries in the array multiple times, essentially adding the same object.

With reference types, you're not storing the value itself, but rather a reference to it, enabling multiple variables to point to the same value.

For instance:

var x = {"name": "John"};
var y = x;
y.name = "John2";

Both x and y will be affected since they both refer to the same object.

To resolve this issue, move the declaration of placeholderSeries inside the loop. This way, a new object will be created in each iteration.

Answer №2

When working with newer versions of JavaScript, the map function can be utilized in the following manner:

// Here is a simplified example using data from an API
const sourceData = {
    "hits": 4,
    "job": [
        {
            "status": "FINISHED",
            "type": "IMPORT"
        },
        {
            "status": "FAILED",
            "type": "EXPORT"
        },
        {
            "status": "RUNNING",
            "type": "TRANSCODE"
        },
        {
            "status": "FINISHED",
            "type": "TRANSCODE"
        }
    ]
};

const labels = [...new Set(sourceData.job.map(item => item.type))];
const uniqueStatuses = [...new Set(sourceData.job.map(item => item.status))];

const resultData = {
    labels,
    series: uniqueStatuses.map(item =>({"name": item, data: []}))
};

console.log(JSON.stringify(resultData, null, 4));

Answer №3

  • statusExists is always = -1
  • You are constantly using .push(placeholderSeries);
  • placeholderSeries remains the same object each time (
    var placeholderSeries = { name: '', data: [] }
    )

During the final iteration loop:

  // status:  [ 'FINISHED', 'FAILED', 'RUNNING' ]
  for (var i = 0; i < ResultData.series.length; i++) {
    // THIS LINE IS NOT WORKING AS EXPECTED
    ResultData.series[i].name = status[i];
  }

We are assigning the value of a single object to 'RUNNING'

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

Deleting all JSON files in a directory using NodeJs

Is there a way to delete only the json files within a directory (multiple levels) without specifying each file name individually? I thought fs-unlinkSync(path) might work, but I haven't found that solution yet. I attempted to use the following method ...

What is the best way to extract a JSON value and use it across multiple functions?

Currently, everything seems to be working fine. However, I'm unsure about the correct way to call the json data. I attempted using a direct link but it didn't work. Do I need to modify the "data" parameters? I'm confused because I saw that ...

Are HTML's Regular Expressions the Equivalent of JavaScript's Regular Expressions?

I have been trying to utilize the pattern="" attribute in HTML to implement regex, but unfortunately, I am unable to locate a comprehensive list of HTML regex parameters. This has led me to ponder whether the syntax for regex in HTML is similar to JavaSc ...

What steps can be taken to avoid the appearance of the JavaScript prompt "Leaving site"?

Hi there, I'm currently trying to find a way to remove the Javascript prompt/confirm message that asks "Do you want to leave this site?" like shown in this link: The issue I am facing is that when a modal opens and the user clicks on "YES", it redire ...

Seeking a quick conversion method for transforming x or x[] into x[] in a single line of code

Is there a concise TypeScript one-liner that can replace the arrayOrMemberToArray function below? function arrayOrMemberToArray<T>(input: T | T[]): T[] { if(Arrary.isArray(input)) return input return [input] } Trying to cram this logic into a te ...

Tips on how to trigger the function upon receiving the response value by concurrently running two asynchronous functions

export default { data: () =>({ data1: [], data2: [], lastData: [] }), mounted() { asynchronous1(val, (data)=>{ return this.data1 = data }) asynchronous2(val, (data)=>{ return this.data2 = data }) f ...

Applying CSS to an iframe using JavaScript: A Step-by-Step

I have an Iframe editor and I am trying to change some CSS inside the editor. However, when I attempt to apply the CSS, it does not affect the styles within the Iframe. <div id="editor" style="flex: 1 1 0%;"> <iframe src="https://editor.unlay ...

Parsing issues arise when parsing large JSON objects in the rtweet package

Having trouble parsing large JSON files using the parse_stream() function from the rwteet library. It seems to fail when processing long JSON objects. The issue arises when dealing with JSON objects of significant size (200MB-1GB). This is how my stream f ...

Retrieve JSON data from an SQL query that includes the term "MariaDB."

If I have a row named "weather" in a MariaDB table with the following information: "Weather today is Sunny - {“temp”: “79”, “rainchance”: “0%”}", how can I extract ONLY the JSON data? I attempted 'JSON_VALUE(weather,'$.temp' ...

What is the process for retrieving the value of `submit.preloader_id = "div#some-id";` within the `beforesend` function of an ajax call?

In my JavaScript code, I have the following written: var formSubmit = { preloaderId: "", send:function (formId) { var url = $(formId).attr("action"); $.ajax({ type: "POST", url: url, data: $(formId).serialize(), dataTy ...

Tips for hiding a soft keyboard with jQuery

Here is a text button: <input type="text" class="field" id="something" name="something" placeholder="text" autofocus /> I want to prevent the android soft keyboard from popping up and keep the focus on this field. I only want to do this for this ...

Is it possible to include two functions within a single HTML script?

On my webpage, there are multiple tabs that display different sets of data. Below is the code for handling the functionality of these tabs: function openTab(event, tabName) { var i, tabcontent, tablinks; tabcontent = document.getElementsByClassNa ...

Techniques for manipulating multiple circles with JavaScript

After creating a series of circles with d3, I successfully implemented the functionality to drag individual circles and track their positions. var width= 800; var height=600; svg= d3.select("body").select(".div1").append("svg") ...

Trouble with Mocha async hooks execution?

I keep encountering the issue of receiving 'undefined' for the page in this setup. It appears that none of Mocha's hooks are being executed. I've attempted adding async to the describe at the top level, used done statements, and even tr ...

Having trouble displaying the output on my console using Node.js

Hey there, I'm new to this community and also new to the world of nodejs technology. I have encountered a problem that may seem minor to you but is quite big for me. Here's what's going on: In my code snippet, I want a user to input 3 value ...

Invoke a jQuery method in a dynamic manner

Is it possible to achieve the following? var todo = "text"; $this.eval(todo).split(/\b[\s,\.-:;]*/).length; The desired function is: $this.text().split(/\b[\s,\.-:;]*/).length; I'm struggling to find a solution... Ca ...

Is there a method to pre-load a CSS background image so that it can still be displayed even without an internet connection?

Situation: Imagine having a web app that shows an error message when trying to perform an action but fails due to a connectivity problem. The error dialogue has a CSS class with a background image that can't load because of the connection issue, res ...

Different Zoom feature for JIT Graph

I'm currently working with the Java Infovis Toolkit and I'd like to use buttons for zooming in and out instead of using the mouse wheel. Can someone guide me on how I can implement two separate buttons for Zoom In and Zoom Out functions? ...

Load JavaScript files in order within the <body> tag and trigger a callback function when all files have

Currently, my website (which is actually a Cordova/Phonegap app) has the following scripts in the <head>: <script type="text/javascript" src="cordova.js"></script> <script type="text/javascript" src="appPolyfills.js"></script> ...

Is there a way to tally the frequency of a specific property appearing in one array within another, and then transfer those matches into a separate array?

My goal is to match the fk_city with the $id of each city in the 'list_cities' array, and then calculate the number of occurrences. const list_cities = [ { $id: '15FG', name: 'Pittsburg' }, { $id: '50HS', name: & ...