"Looping" through objects

Can this code be refactored? It looks really ugly to me, but working with objects - as opposed to arrays - always results in ugly code, at least for me. Ideas welcome - thanks!

Data:

Output required:
I need each of the properties of each of the objects (i.e. rows from data above) to be converted into numbers. All except the first property which I need to remain a text value.

d3.csv("data/Book2.csv").then(function(data) {
  console.log(data);

  
  data.forEach(function(d) {
    //Update all values to be numbers instead of string
    for (let property in d) {
      let allowableKeys =
        d[property] !== "Number of Agents" &&
        d[property] !== "Number of Active BB Agents" &&
        d[property] !== "Number of Accounts" &&
        d[property] !== "Active Accounts" &&
        d[property] !== "Deposits as of date (Rs. in millions )" &&
        d[property] !== "Number of transactions during the quarter" &&
        d[property] !==
          "Value of transactions during the quarter(Rs. in millions)" &&
        d[property] !== "Average Size of transaction (in Rupees)" &&
        d[property] !== "Average number of transaction per day";

      if (d.hasOwnProperty(property) && allowableKeys) {
        d[property] = parseFloat(d[property].replace(/,/g, ""));
      }
    }

    dataNumAgent = data.filter(d => d.Indicator === "Number of Agents");
    dataNumActAgent = data.filter(
      d => d.Indicator === "Number of Active BB Agents"
    );
  });

  //x-scale:
  // let xScale = d3.scaleTime.domain().range();
});

Can you post the result of console.log(JSON.stringify(data))?

Or put console.log(JSON,stringify(d)) for the first iteration of the forEach?

Below is console.log(data) and console.log(JSON.stringify(data)):

Thanks for the screen shot. This clears things up for me. Would you mind actually copying/pasting the results of the console.log(JSON.stringify(data)) instead of a screenshot into a reply? I want to test something before I post my response with a proposed solution.

1 Like

It’s highly unnecessary to have that huge allowableKeys thing in your code. You only need to check against ‘Indicator’ as a property name:

  if (columnName !== "Indicator") {
    /* Do stuff */
  }
}
1 Like

[{“Indicator”:“Number of Agents”,“3/1/2017”:“368,738”,“6/1/2017”:“402,710”,“9/1/2017”:“420,107”,“12/1/2017”:“405,673”},{“Indicator”:“Number of Active BB Agents”,“3/1/2017”:“213,068”,“6/1/2017”:“185,297”,“9/1/2017”:“181,377”,“12/1/2017”:“192,741”},{“Indicator”:“Number of Accounts”,“3/1/2017”:“23,685,630”,“6/1/2017”:“27,312,964”,“9/1/2017”:“33,070,736”,“12/1/2017”:“37,260,215”},{“Indicator”:“Active Accounts”,“3/1/2017”:“11,287,857”,“6/1/2017”:“13,158,310”,“9/1/2017”:“15,526,367”,“12/1/2017”:“19,259,427”},{“Indicator”:“Deposits as of date (Rs. in millions )”,“3/1/2017”:“7,906”,“6/1/2017”:“15,423”,“9/1/2017”:“11,280”,“12/1/2017”:“21,139”},{“Indicator”:“Number of transactions during the quarter”,“3/1/2017”:“140,589”,“6/1/2017”:“167,173”,“9/1/2017”:“164,704”,“12/1/2017”:“175,149”},{“Indicator”:“Value of transactions during the quarter(Rs. in millions)”,“3/1/2017”:“564,448”,“6/1/2017”:“746,569”,“9/1/2017”:“726,451”,“12/1/2017”:“766,540”},{“Indicator”:“Average Size of transaction (in Rupees)”,“3/1/2017”:“4,015”,“6/1/2017”:“4,466”,“9/1/2017”:“4,411”,“12/1/2017”:“4,377”},{“Indicator”:“Average number of transaction per day”,“3/1/2017”:“1,562,096”,“6/1/2017”:“1,857,476”,“9/1/2017”:“1,830,042”,“12/1/2017”:“1,946,100”}]

You really only want to convert the values of property names (keys) which are dates. Why not use Date.parse(theValue) to check if it results in a number (truthy value) instead of NaN (falsy value) which it will return if the string is not a date?

const convertedData = data.map(row => {
  return Object.entries(row).reduce((obj, [ key, value ]) => {
    obj[key] = Date.parse(key) ? Number(value.replace(/,/g,'')) : value;
    return obj;
  }, {});
});
1 Like

This is what I ended up with (took @luishendrix92 advice). Am I over-simplifying by using , "property !== "Indicator"?

    for (let property in d) {
      if (d.hasOwnProperty(property) && property !== "Indicator") {
        d[property] = parseFloat(d[property].replace(/,/g, ""));
      }
    }
2 Likes