0

I have an array of objects

  var input = [
      {
        "cropName": "chickpea (bengal gram)",
        "netSownArea": "1"
      },
      {
        "cropName": "chickpea (bengal gram)",
        "netSownArea": "1"
      },
      {
        "cropName": "chickpea (bengal gram)",
        "netSownArea": "1"
      },
      {
        "cropName": "chickpea (bengal gram)",
        "netSownArea": "1"
      },
      {
        "cropName": "maize",
        "netSownArea": "1"
      },
      {
        "cropName": "maize",
        "netSownArea": "1"
      }
    ];

How can I add duplicate cropname area and unique value should be as it is

[
      {
        "cropName": "chickpea (bengal gram)",
        "netSownArea": "4"
      },
      {
        "cropName": "maize",
        "netSownArea": "2"
      }
    ]

I have tried below solution but it returns only unique value

     function grouping(input) {
     const res = Array.from(new Set(input.map(s => s.cropName)))
             .map(cropName => {
                 return {
                     cropName: cropName,
                     netSownArea: input.find(s => s.cropName === cropName).netSownArea

                 }
             });

         return res;
     };
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
  • 1
    Possible duplicate of [Most efficient method to groupby on an array of objects](https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects) – Heretic Monkey Oct 25 '19 at 17:38

3 Answers3

0

    var input = [
              {
                "cropName": "chickpea (bengal gram)",
                "netSownArea": "1"
              },
              {
                "cropName": "chickpea (bengal gram)",
                "netSownArea": "1"
              },
              {
                "cropName": "chickpea (bengal gram)",
                "netSownArea": "1"
              },
              {
                "cropName": "chickpea (bengal gram)",
                "netSownArea": "1"
              },
              {
                "cropName": "maize",
                "netSownArea": "1"
              },
              {
                "cropName": "maize",
                "netSownArea": "1"
              }
            ];
    var z = input.reduce((res , item) => {
      const index = res.findIndex(r => {return item.cropName === r.cropName});
      if (index !== -1) {
        res[index]['netSownArea'] = Number(res[index]['netSownArea']) +1;
      } else {
        res.push(item);
      }
      return res;
    }, []);
    
    console.log(z);
var input = [
          {
            "cropName": "chickpea (bengal gram)",
            "netSownArea": "1"
          },
          {
            "cropName": "chickpea (bengal gram)",
            "netSownArea": "1"
          },
          {
            "cropName": "chickpea (bengal gram)",
            "netSownArea": "1"
          },
          {
            "cropName": "chickpea (bengal gram)",
            "netSownArea": "1"
          },
          {
            "cropName": "maize",
            "netSownArea": "1"
          },
          {
            "cropName": "maize",
            "netSownArea": "1"
          }
        ];
var z = input.reduce((res , item) => {
  const index = res.findIndex(r => {return item.cropName === r.cropName});
  if (index !== -1) {
    res[index]['netSownArea'] = Number(res[index]['netSownArea']) +1;
  } else {
    res.push(item);
  }
  return res;
}, []);

console.log(z);

I am using reduce for accumulated result.

Nitin Shekhar
  • 175
  • 2
  • 15
0

You can do it by using nested loops. Incrementing the value of the object in the array if it exists else adding it in array.

var input = [
 {
  "cropName": "chickpea (bengal gram)",
  "netSownArea": "1"
 },
 {
  "cropName": "chickpea (bengal gram)",
  "netSownArea": "1"
 },
 {
  "cropName": "chickpea (bengal gram)",
  "netSownArea": "1"
 },
 {
  "cropName": "chickpea (bengal gram)",
  "netSownArea": "1"
 },
 {
  "cropName": "maize",
  "netSownArea": "1"
 },
 {
  "cropName": "maize",
  "netSownArea": "1"
 }
 ];

 let ans = [];
 input.forEach((val)=>{
  let cropName = val.cropName;
  let i =0;
  for(i=0;i<ans.length;i++){
   if(ans[i].cropName == cropName){
    ans[i].netSownArea = parseInt(ans[i].netSownArea) + 1;
    break;
   }                
  }
  if( i == ans.length){
   ans.push({"cropName":cropName,"netSownArea":1});
  } 
  
 })

 console.log(ans);
Akshay Bande
  • 2,491
  • 2
  • 12
  • 29
0

The most efficient way to handle your use case would be to build up a lookup table while processing the array (allowing you to immediately know if there is a previous match or not).

I notice that both of the other answers are looping through the results so far for each input element to find a match which is not efficient (in big O notation, we are talking about O(n*m) instead of the more efficient O(n+m) for the answer, where n is the number of elements in the input array and m is the number of elements in the results array).

const lookup = input.reduce((acc, value) => {
  const cropName = value.cropName;

  if (!acc[cropName]) {
    acc[cropName] = { ...value, netSownArea: 0 }; // makes a copy so not modifying the actual array item and initializes the count to 0
  }

  acc[cropName].netSownArea += +value.netSownArea; // use the unary plus operator to convert to a number

  return acc;
}, {});

const results = Object.values(lookup); // grabs each item in the lookup table
Daniel W Strimpel
  • 8,190
  • 2
  • 28
  • 38