Exploring the process of iterating through and organizing a JavaScript array

Recently, I encountered a JavaScript object that was generated by a particular API. The object is structured in a way that it can potentially have multiple instances of the same 'equity' (such as Hitachi Home in this case):

  {
    "results": {
      "holdings": [{
        "equity": {
          "text": "Hitachi Home"
        },
        "holding_pc": "6.48",
        "sector": "Consumer Durables",
        "shares_no": "1537.00",
        "value_cr": "0.24"
      }, {
        "equity": {
          "text": "Mahindra CIE"
        },
        "holding_pc": "6.34",
        "sector": "Manufacturing",
        "shares_no": "10376.00",
        "value_cr": "0.24"
      }, {
        "equity": {
          "text": "Schneider Infra"
        },
        "holding_pc": "5.33",
        "sector": "Utilities",
        "shares_no": "9518.00",
        "value_cr": "0.20",
      }, {
        "equity": {
          "text": "Hitachi Home"
        },
        "holding_pc": "2.18",
        "sector": "Consumer Durables",
        "shares_no": "437.00",
        "value_cr": "0.12"
      }]
    }
  }

I am currently exploring the best approach to develop a JavaScript function that can take this entire object as input, iterate through all the records, and consolidate the data so that records with the same 'equity' are summed and merged. For example, the equity 'Hitachi Home' should be consolidated as follows:

  {
    "results": {
      "holdings": [{
        "equity": {
          "text": "Hitachi Home"
        },
        "holding_pc": "8.66",
        "sector": "Consumer Durables",
        "shares_no": "1974.00",
        "value_cr": "0.36"
      }, {
        "equity": {
          "text": "Mahindra CIE"
        },
        "holding_pc": "6.34",
        "sector": "Manufacturing",
        "shares_no": "10376.00",
        "value_cr": "0.24"
      }, {
        "equity": {
          "text": "Schneider Infra"
        },
        "holding_pc": "5.33",
        "sector": "Utilities",
        "shares_no": "9518.00",
        "value_cr": "0.20",
      }]
    }
  }

My objective is to create a JS function that can aggregate all equities with the same text. Below is a high-level overview of the function I am working on:

function transform(data) {
  function sumHoldings(row) {
    newrow = {};
    newrow.equity = row.equity.text;
    newrow.holding_pc = row.holding_pc;
    return newrow;
  }
  for(var holdings in data.results) {
    data.results.total_holdings = data.results.holdings.map(sumHoldings);
  };

  return data;
}

Answer №1

You can condense the initial array in the following manner:

var data = {
  "data": {
    "items": [{
      "name": {
        "text": "Apple"
      },
      "quantity": "10",
      "category": "Fruits",
      "price": "2.50"
    }, {
      "name": {
        "text": "Carrot"
      },
      "quantity": "15",
      "category": "Vegetables",
      "price": "1.20"
    }, {
      "name": {
        "text": "Banana"
      },
      "quantity": "20",
      "category": "Fruits",
      "price": "0.80"
    }, {
      "name": {
        "text": "Carrot"
      },
      "quantity": "5",
      "category": "Vegetables",
      "price": "0.60"
    }]
  }
}

function findFirstElement(elements, condition) {
  for (var i = 0; i < elements.length; i++) {
    if (condition(elements[i])) {
      return elements[i];
    }
  }
  return null;
}

var condensedResult = data.data.items.reduce(function (arr, item) {
  item.quantity = Number(item.quantity);
  item.price = Number(item.price);
  var element = findFirstElement(arr, function (_item) { return _item.name.text === item.name.text });
  if (element) {
    // If element is found, perform calculations
    element.quantity += item.quantity;
    element.price += item.price;
  } else {
    // If element is not found, add to the array
    arr.push(item);
  }
  return arr;
}, []);


document.querySelector('#output').innerHTML = JSON.stringify({ data: { items: condensedResult } }, undefined, 4);
<pre id="output"></pre>

Answer №2

To streamline your data management process, I recommend creating a holdings object that can consolidate all the necessary information and be easily accessed using unique holdings names.

One way to achieve this is by iterating through your holdings array and transferring the data from the original object to a new consolidatedHoldings object. Here's a general outline of how you can do this:

var consolidatedHoldings = {};

obj.results.holdings.forEach(function(holding){
    holding.forEach(function (holdingDataValue, holdingDataIndex) {
        if (!isNaN(parseFloat(holdingDataValue)) && isFinite(holdingDataValue)) {
            consolidatedHoldings[holdingDataIndex] = consolidatedHoldings[holdingDataIndex] + parseFloat(holdingDataValue);
        } else {
            consolidatedHoldings[holdingDataValue] = holdingDataValue;
        }
    });
});

By following this approach, you can ensure that the consolidated holdings object is accurately updated. Any new keys will be created if they don't already exist, and existing keys will be overwritten with the updated data. Additionally, numerical values will be added together.

Once you have the consolidated holdings object, you may consider converting it into an array and integrating it back into your original object for easier data management.

Answer №3

let holdingsMap = {};

a.holdings.forEach(function(holding){  
   let text = holding.equity.text;
   let entry = holdingsMap[text] || (holdingsMap[text] = []);

   entry.push(holding);
});

Object.keys(holdingsMap).map(function(key) {
  let values = holdingsMap[key];
  let parseFloats = function(a, b) { return parseFloat(a) + parseFloat(b); };

  return {
     equity: {
        "text" : key
     },
     sector : values[0].sector,
     value_cr: values.map(function(e) { return e.value_cr; }).reduce(parseFloats, 0), 
     shares_no: values.map(function(e) { return e.shares_no; }).reduce(parseFloats, 0), 
     holding_pc : values.map(function(e) { return e.holding_pc; }).reduce(parseFloats, 0)
   }
});

Answer №4

To optimize your code, make sure to iterate through the arrays instead of the objects. This will allow you to efficiently access the properties of the object. Consider the following approach:

obj.results.holdings.forEach(function(holding){
    // Access the equity string using holding.equity.text
    // Handle uniqueness as needed, such as by adding it to an array only if it's not already included
});

Upon further review, it seems that your goal is to reduce the array, not just find unique elements. You can achieve this by:

var equity = { };
var sums = ['holding_pc', 'shares_no', 'value_cr'];
var holdings = obj.results.holdings.reduce(function(previousValue, currentValue){
    var currentEquity = currentValue.equity.text;
    if(equity[currentEquity] !== undefined){
        // Update existing equity values in the reduced array
        oldObj = previousValue[equity[currentEquity]];
        sums.forEach(function(prop){
           oldObj[prop] = Number(oldObj[prop]) + Number(currentValue[prop]); 
        });
    } else {
        // Add new equity values to the reduced array
        equity[currentEquity] = previousValue.length;
        previousValue.push(currentValue);
    }
    return previousValue;
}, []);
// The holdings variable now contains the reduced array of objects

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

Mastering the Art of Writing an Ajax Post Request

I am attempting to transmit an image URL to a node.js server from some JavaScript using the Ajax POST method. My expectation is for the server to respond with some text, but I'm encountering issues and unsure where the problem lies. Below is the relev ...

Learn the steps to create a 3D carousel that spins on its own without the need for manual clicks and pauses once the

Looking for a solution to create a 3D carousel that rotates continuously without the need for buttons to be clicked, and pauses when the mouse hovers over it, then resumes rotation when the mouse is not hovering over it. var carousel = $(".carousel"), ...

Utilizing HTML to call a function and fetching data from AngularJS

I've been struggling to retrieve the value after calling a function in my HTML file. Despite trying various methods after conducting research, I have not achieved success yet. Take a look at the code below: HTML: <div class="form-group"> & ...

Detect Flash Player Event using Javascript

Is there a way to detect when a flash video ends without depending on user input like clicking the stop button? It's important to note: I HAVE NO CONTROL OVER THE PRESENTATIONS OR SWF FILES. My goal is to automate the client player object through s ...

Embedding JSON data in a GSP page

My goal is to transfer JSON data to a GSP page and present it in a table format. The expected JSON structure: { "data": [ [ "Tiger Nixon", "System Architect", "Edinburgh" ] ]} I attempted to achieve this with the following co ...

What is the best way to utilize functions from different JavaScript files?

I'm currently handling server-side javascript and I've got confidential data that needs to remain secure, stored in a private directory. If I choose to enclose this data within a function, how can I go about invoking that function from a separate ...

Displaying identification when clicked using JavaScript

Hey there, I've been searching for an answer to my issue but haven't had any luck so far. Can anyone assist me? I have a group of links that display specific ids when clicked. It's working fine, but one link should actually trigger the disp ...

Encountering Next.JS Router Issue: Unable to Access Properties of Null (specifically 'useContext')

As a beginner in Next.js and React, I'm facing an issue with redirecting users from the "Projects" page to the Product Page Details. Here's the code snippet I am using: const openProjectDetails = () => { Router.push('/api/' + props ...

Using Codeception's selenium module to wait for JavaScript and Ajax requests to

I am currently facing an issue where I need to wait for an ajax call to finish loading before moving on to the next step. I have tried using the waitForJS function, but I am struggling with building the JavaScript condition. I have experimented with diffe ...

Creating a Node.js asynchronous setup function

I'm in the process of transitioning from Nodejs v12 to v14 and I've noticed that v14 no longer waits for the setup function to resolve. My setup involves Nodejs combined with Express. Here's a simplified version of my code: setup().then(cont ...

What is the best way to choose two <li> elements with multiple classes in my WordPress navigation menu?

I am looking for a JavaScript function that will add the class "current_highlight" when an element with the class "activo2" also has the class "active". Here is my HTML code: <div class="navbar-header"> <button type="button " class="navbar-to ...

How can I align rectangles with different heights to display side by side using Javascript?

Currently, I am designing a press page for a website where the headlines/articles are displayed in rectangles. To achieve this layout, I am using the following CSS: .press-blocks{ column-count: 4; column-gap: 2em; padding-left: 10%; padding ...

The use of custom loaders alongside ts-node allows for more flexibility

Is it possible to utilize ts-node with a custom loader? The documentation only mentions enabling esm compatibility. ts-node --esm my-file.ts I am attempting to implement a custom loader for testing an ESM module, but I prefer not to rely on node for compi ...

Using " " to split a name into two lines is not being recognized

My issue involves the display of tab names in two lines within multiple tabs. You can view the demonstration here. I attempted to use the \n character while setting the tab name but it was not recognized. Any suggestions on how to achieve this? Here ...

When creating a new instance of the Date object in Javascript, the constructor will output a date that is

In my project using TypeScript (Angular 5), I encountered the following scenario: let date = new Date(2018, 8, 17, 14, 0); The expected output should be "Fri Aug 17 2018 14:00:00 GMT-0400 (Eastern Daylight Time)", but instead, it is returning: Mon Sep ...

How can I pass a specific value, rather than the entire array, in a ReactJS dropdown menu?

I am facing a problem where the entire array is being passed as an argument when I call onchange after getting correct values in the dropdown. Instead of only receiving the selected value, e contains the whole array. Here is the code snippet that demonst ...

Using Three.js to create smooth rotations for objects

I have a logo in .obj format that I am loading onto a canvas using three.js. The logo is an integral part of the website's loading section that I am currently developing. Within this section, there is a 'Click to Enter' button. My goal is fo ...

Identify unique special characters without the need for a specific key code

When you press the backspace key, the console may display an empty string for keyVal, which can be misleading because even though it appears empty, keyVal.length is actually equal to 1 due to a hidden character. element.on('keydown',function(e){ ...

Identifying page elements in Protractor when they lack obvious identifiable properties

Scenario Here is the HTML code snippet using an Angular JS template: <div class="data-handler-container"> <div class="row"> <div class="data-handler" ng-if="dataController.showDistance()"> <p>{{ 'Item ...

The initial value for the `useState` is not defined at the

Here's a simplified version of my requirement that demonstrates the issue. The ColorBox component receives a prop called "isVisible" from the ShowColorComponent component, which is used to initially set the state of the ColorBox.visible variable. impo ...