Harith Siddiqui
Harith Siddiqui

Reputation: 9

JavsScript - Looping through Nested Array

I have a nested JSON file of financial portfolios. I need to grab the security_type from each holding for all portfolios_accounts (in the sample JSON there will only be one), as well as the summed up net worth from every individual holding, on a per-portfolio basis, all in a loop.

Eventually, I am trying to use this information to display in a pie chart that is separated based on net worth of security type.

JSON file:

{
    "id": 1,
    "username": "Test",
    "portfolio_accounts": [
        {
            "id": 1,
            "user": 1,
            "username": "Test",
            "account_type": "IRA",
            "name": "MyTestAccount",
            "description": "Just a Test",
            "balance": 100.00,
            "holdings": [
                {
                    "id": 1,
                    "portfolio_id": 2,
                    "security_type": "Stock",
                    "ticker": "GOOG",
                    "price": 1000.50,
                    "shares": 20,
                    "purchase_date": "02-20-2021",
                    "cost_basis": 800.50
                }, 
                {
                    "id": 2,
                    "portfolio_id": 2,
                    "security_type": "Bond",
                    "ticker": "AMZN",
                    "price": 100.99,
                    "shares": 4,
                    "purchase_date": "02-20-2021",
                    "cost_basis": 60.65
                }
            ]
        },
        {
            "id": 2,
            "user": 1,
            "username": "Test",
            "account_type": "IRA",
            "name": "MyTestAccount2 - Electric Boogaloo",
            "description": "Repeat",
            "balance": 100.00,
            "holdings": [
                {
                    "id": 3,
                    "portfolio_id": 3,
                    "security_type": "Bond",
                    "ticker": "GNMA",
                    "price": 530.50,
                    "shares": 2,
                    "purchase_date": "02-20-2021",
                    "cost_basis": 40.20
                }
            ]
        }
    ]
}

Example of the expected pie chart output of this JSON:

A pie chart with one color for bonds ($1,464.96) and one for stocks ($20,010) filled in proportionally. If there were other security types, like crypto, I will need to do the same thing and add in a third color automatically (and so on and so forth).

Upvotes: 0

Views: 49

Answers (3)

vincent
vincent

Reputation: 2181

Big fan of flexible solutions, so here is one using object-scan

// const objectScan = require('object-scan');

const data = { id: 1, username: 'Test', portfolio_accounts: [{ id: 1, user: 1, username: 'Test', account_type: 'IRA', name: 'MyTestAccount', description: 'Just a Test', balance: 100.00, holdings: [{ id: 1, portfolio_id: 2, security_type: 'Stock', ticker: 'GOOG', price: 1000.50, shares: 20, purchase_date: '02-20-2021', cost_basis: 800.50 }, { id: 2, portfolio_id: 2, security_type: 'Bond', ticker: 'AMZN', price: 100.99, shares: 4, purchase_date: '02-20-2021', cost_basis: 60.65 }] }, { id: 2, user: 1, username: 'Test', account_type: 'IRA', name: 'MyTestAccount2 - Electric Boogaloo', description: 'Repeat', balance: 100.00, holdings: [{ id: 3, portfolio_id: 3, security_type: 'Bond', ticker: 'GNMA', price: 530.50, shares: 2, purchase_date: '02-20-2021', cost_basis: 40.20 }] }] };

const r = objectScan(['portfolio_accounts[*].holdings[*]'], {
  reverse: false,
  filterFn: ({
    value: { shares, price, security_type: securityType },
    context: { holdings, totals }
  }) => {
    const netWorth = shares * price;
    holdings.push({ [securityType]: netWorth });
    if (!(securityType in totals)) {
      totals[securityType] = 0;
    }
    totals[securityType] += netWorth;
  }
})(data, {
  holdings: [],
  totals: {}
});

console.log(r);
/* =>
{
  holdings: [ { Stock: 20010 }, { Bond: 403.96 }, { Bond: 1061 } ],
  totals: { Stock: 20010, Bond: 1464.96 }
}
 */
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Disclaimer: I'm the author of object-scan

Upvotes: 0

Mister Jojo
Mister Jojo

Reputation: 22320

const data = 
  { id       : 1
  , username : 'Test'
  , portfolio_accounts: 
    [ { id           : 1
      , user         : 1
      , username     : 'Test'
      , account_type : 'IRA'
      , name         : 'MyTestAccount'
      , description  : 'Just a Test'
      , balance      : 100.00
      , holdings: 
        [ { id            : 1
          , portfolio_id  : 2
          , security_type : 'Stock'
          , ticker        : 'GOOG'
          , price         : 1000.50
          , shares        : 20
          , purchase_date : '02-20-2021'
          , cost_basis    : 800.50
          } 
        , { id            : 2
          , portfolio_id  : 2
          , security_type : 'Bond'
          , ticker        : 'AMZN'
          , price         : 100.99
          , shares        : 4
          , purchase_date : '02-20-2021'
          , cost_basis    : 60.65
      } ] } 
    , { id           : 2
      , user         : 1
      , username     : 'Test'
      , account_type : 'IRA'
      , name         : 'MyTestAccount2 - Electric Boogaloo'
      , description  : 'Repeat'
      , balance      : 100.00
      , holdings: 
        [ { id            : 3
          , portfolio_id  : 3
          , security_type : 'Bond'
          , ticker        : 'GNMA'
          , price         : 530.50
          , shares        : 2
          , purchase_date : '02-20-2021'
          , cost_basis    : 40.20
  } ] } ] } 
, security_types = { Stock : 0, Bond : 0 }
  ;
for(let ptfAcc of data.portfolio_accounts ) 
for(let hld    of ptfAcc.holdings )
  security_types[hld.security_type] += (hld.price * hld.shares)
  ;
console.log( security_types )

Upvotes: 1

Alessio Cantarella
Alessio Cantarella

Reputation: 5201

You could create an object with all the possible security types set to 0, then sum there every holding, e.g.:

let data = {
    "id": 1,
    "username": "Test",
    "portfolio_accounts": [
        {
            "id": 1,
            "user": 1,
            "username": "Test",
            "account_type": "IRA",
            "name": "MyTestAccount",
            "description": "Just a Test",
            "balance": 100.00,
            "holdings": [
                {
                    "id": 1,
                    "portfolio_id": 2,
                    "security_type": "Stock",
                    "ticker": "GOOG",
                    "price": 1000.50,
                    "shares": 20,
                    "purchase_date": "02-20-2021",
                    "cost_basis": 800.50
                }, 
                {
                    "id": 2,
                    "portfolio_id": 2,
                    "security_type": "Bond",
                    "ticker": "AMZN",
                    "price": 100.99,
                    "shares": 4,
                    "purchase_date": "02-20-2021",
                    "cost_basis": 60.65
                }
            ]
        },
        {
            "id": 2,
            "user": 1,
            "username": "Test",
            "account_type": "IRA",
            "name": "MyTestAccount2 - Electric Boogaloo",
            "description": "Repeat",
            "balance": 100.00,
            "holdings": [
                {
                    "id": 3,
                    "portfolio_id": 3,
                    "security_type": "Bond",
                    "ticker": "GNMA",
                    "price": 530.50,
                    "shares": 2,
                    "purchase_date": "02-20-2021",
                    "cost_basis": 40.20
                }
            ]
        }
    ]
};
let security_types = {
  Bond: 0,
  Stock: 0,
  Crypto: 0
};
data.portfolio_accounts.forEach(portfolio_account => {
  portfolio_account.holdings.forEach(holding => {
    security_types[holding.security_type] += holding.price * holding.shares;
  });
});
console.log(security_types);

Upvotes: 0

Related Questions