4
\$\begingroup\$

I want a JSON object of the following structure to plot a chart

chartGroup = [{name: 'A<->B', to: 254, from: 247},
              {name: 'C<->D', to: 208, from: 211},
              {name: 'A<->C', to: 46, from: 41},
              {name: 'A<->D', to: 10, from: 38},
              {name: 'B<->C', to: 56, from: 55},
              {name: 'B<->D', to: 44, from: 45}
             ];

from the below JSON object which I get from Database

data = [{from: "B", to: "D", count: 44},
        {from: "D", to: "B", count: 45},
        {from: "A", to: "B", count: 254},
        {from: "C", to: "D", count: 208},
        {from: "B", to: "A", count: 247},
        {from: "C", to: "A", count: 41},
        {from: "A", to: "D", count: 10},
        {from: "A", to: "C", count: 46},
        {from: "D", to: "C", count: 211},
        {from: "D", to: "A", count: 38},
        {from: "C", to: "B", count: 55},
        {from: "B", to: "C", count: 56}];

To create chartGroup from data, I'm using the below code :

     var chartPoints = {};
     data.forEach(function(s) {
        if((s.from == "A" && s.to == "B") || (s.from == "B" && s.to == "A")) {
            if(s.to == "B"){
                chartPoints["to"] = s.count;
            }else{
                chartPoints["from"] = s.count;
            }
            chartPoints["name"] = "A<->B";

         }             
     });
   chartGroup.push(chartPoints);

   var chartPoints = {};
   data.forEach(function(s) {
       if((s.from == "C" && s.to == "D") || (s.from == "D" && s.to == "C")) {
           if(s.to == "D"){
               chartPoints["to"] = s.count;
           }else{
               chartPoints["from"] = s.count;
           }
           chartPoints["name"] = "C<->D";                            
       }             
   });
   chartGroup.push(chartPoints);

   var chartPoints = {};
   data.forEach(function(s) {
       if((s.from == "A" && s.to == "C") || (s.from == "C" && s.to == "A")) {
           if(s.to == "C") {
               chartPoints["to"] = s.count;
           }else{
               chartPoints["from"] = s.count;
           }
           chartPoints["name"] = "A<->C";
    }     
  });
  chartGroup.push(chartPoints);

  var chartPoints = {};
  data.forEach(function(s) {
      if((s.from == "A" && s.to == "D") || (s.from == "D" && s.to == "A")) {
          if(s.to == "D") {
             chartPoints["to"] = s.count;
          }else{
             chartPoints["from"] = s.count;
          }
          chartPoints["name"] = "A<->D";   
     }    
  });
  chartGroup.push(chartPoints);

  var chartPoints = {};
  data.forEach(function(s) {
      if((s.from == "B" && s.to == "C") || (s.from == "C" && s.to == "B")) {
          if(s.to == "C") {
              chartPoints["to"] = s.count;
          }else{
              chartPoints["from"] = s.count;
          }
          chartPoints["name"] = "B<->C"; 
     }                  
   });
   chartGroup.push(chartPoints);

   var chartPoints = {};
   data.forEach(function(s) {
       if((s.from == "B" && s.to == "D") || (s.from == "D" && s.to == "B")) {
       if(s.to == "D"){
           chartPoints["to"] = s.count;
       }else{
           chartPoints["from"] = s.count;
       }
       chartPoints["name"] = "B<->D"; 
    }      
  }); 
  chartGroup.push(chartPoints);

would like to know if there is a better way to reduce the JSON object. As it can be seen that there is lot of loops and conditions which is not good. Please don't give importance to typo as I have modified the data to a example.

\$\endgroup\$
2
\$\begingroup\$

Your code had a lot of loops so I tried to squish it into one reducer for you. I think this will work;

var output = data.reduce(function (out, d) {
   var edges = [d.from, d.to].sort();
   var key = edges.join("<->");
   var obj = out.find(function (o) { return o.name === key; });
   if (!obj) {
     obj = {
       name: key,
       from: 0,
       to: 0
     };
     out.push(obj);
   }
   obj.to += edges[0] === d.from ? d.count : 0;
   obj.from += edges[1] === d.from ? d.count : 0;

   return out;
 }, []);

console.log(output);

Output:

[
  {
    "name": "B<->D",
    "from": 45,
    "to": 44
  },
  {
    "name": "A<->B",
    "from": 247,
    "to": 254
  },
  {
    "name": "C<->D",
    "from": 211,
    "to": 208
  },
  {
    "name": "A<->C",
    "from": 41,
    "to": 46
  },
  {
    "name": "A<->D",
    "from": 38,
    "to": 10
  },
  {
    "name": "B<->C",
    "from": 55,
    "to": 56
  }
]

Here's an example on JsBin

Reducers are super powerful when you need to convert an array into a different array or value.

In this case I'm iterating over the data array, and creating the key (A<=>B) by sorting the from and to values.

Then I check the output to see if we've already used that key, if so we append to that existing object, if not then we create it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.