Manish Verma
Manish Verma

Reputation: 17

How to group yield value based on date key from array of object in javascript

I have an array of objects

var data = [
    {
        "date": "2016-07-18T00:00:00.000+0000",
        "boundaryStats": [
            {
                "crop": 'Wheat',
                "yield": 27,
            },
            {
                "crop": 'Maize',
                "yield": 48,
            }
        ]
    },
    {
        "date": "2020-03-18T00:00:00.000+0000",
        "boundaryStats": [
            {
                "crop": "garlic",
                "yield": 12,
            },
            {
                "crop": "Wheat",
                "yield": 12,
            }
        ]
    },
    {
        "date": "2020-07-18T00:00:00.000+0000",
        "boundaryStats": [{
            "crop": "Onion",
            "yield": 1,
        }
    ]
    }
];

How can I get the output as below only unique crop name will be added and the length of data is based on length of the input array date, 0 if there is no data for the particular date

[{
        "label": "Wheat",
        "data": [27,12,0]
    },
    {
        "label": "Maize",
        "data": [48,0,0]
    },
    {
        "label": "garlic",
        "data": [0,12,0]
    },
    {
        "label": "Onion",
        "data": [0,0,1]
    }
]

I tried

    main = [];
resultObj = new Array(this.data.length).fill(0);
this.data.forEach(e=>{
  e.boundaryStats.forEach((ei,i)=>{    
const checkUsername = obj => obj.label === ei.crop;

    if(!main.some(checkUsername)){
    main.push({
      'label':ei.crop,
      'data':resultObj
      })
    }
  })
})

but yield I am not able to add a particular data index

Upvotes: 1

Views: 100

Answers (5)

Rajneesh
Rajneesh

Reputation: 5308

You can first maintain a date Object with its initial count, then you can reduce it:

var data = [ { "date": "2016-07-18T00:00:00.000+0000", "boundaryStats": [ { "crop": 'Wheat', "yield": 27, }, { "crop": 'Maize', "yield": 48, } ] }, { "date": "2020-03-18T00:00:00.000+0000", "boundaryStats": [ { "crop": "garlic", "yield": 12, }, { "crop": "Wheat", "yield": 12, } ] }, { "date": "2020-07-18T00:00:00.000+0000", "boundaryStats": [{ "crop": "Onion", "yield": 1, } ] }];

var datesOrder = Object.fromEntries(data.map(({date})=>([new Date(date).toLocaleDateString(),0])));

result = Object.values(data.reduce((acc, {date, boundaryStats})=>{
  boundaryStats.forEach(k=>{
    acc[k.crop] = acc[k.crop] || {label:k.crop, data:{...datesOrder}};
    acc[k.crop].data[new Date(date).toLocaleDateString()] = k.yield;
 });
return acc;
},{}))
  .map(({label, data})=>({label, data:Object.values(data)}));

console.log(result);

Upvotes: 0

Alex L
Alex L

Reputation: 4241

We can do it with reduce:

const dateArr = data.map(item => (new Date(item.date)).toLocaleString()); //can be sorted if needed

console.log(dateArr);

const tempOut = data.reduce((aggObj, item) => {
  
  item.boundaryStats.forEach(stat => {
    const statDate = (new Date(item.date)).toLocaleString();
    if (!aggObj[stat.crop]){
      aggObj[stat.crop] = {label: stat.crop, data: {}};
      for (let date of dateArr){
        aggObj[stat.crop].data[date] = 0;
      }
    }
    aggObj[stat.crop].data[statDate] += stat.yield;
  })
  
  return aggObj;
}, {})

//console.log(tempOut)

const finalOut = Object.values(tempOut).map(crop => {
  crop.data = Object.values(crop.data);
  return crop
});

console.log(finalOut);
<script id="initData">

const data = [
    {
        "date": "2016-07-18T00:00:00.000+0000",
        "boundaryStats": [
            {
                "crop": 'Wheat',
                "yield": 27,
            },
            {
                "crop": 'Maize',
                "yield": 48,
            }
        ]
    },
    {
        "date": "2020-03-18T00:00:00.000+0000",
        "boundaryStats": [
            {
                "crop": "garlic",
                "yield": 12,
            },
            {
                "crop": "Wheat",
                "yield": 12,
            }
        ]
    },
    {
        "date": "2020-07-18T00:00:00.000+0000",
        "boundaryStats": [{
            "crop": "Onion",
            "yield": 1,
        }
    ]
    }
];
</script>

Upvotes: 0

user120242
user120242

Reputation: 15268

Uses an object map to collect values. map to desired {label,data} objects at the end.

const map = {}
data.forEach(({boundaryStats: b},i)=>b.forEach(({crop, yield})=>{
  map[crop] = map[crop] || Array(data.length).fill(0)
  map[crop][i] = yield
}))

console.log(
Object.entries(map).map(([crop,yield])=>({label:crop, data:yield}))
)
<script>
var data = [
    {
        "date": "2016-07-18T00:00:00.000+0000",
        "boundaryStats": [
            {
                "crop": 'Wheat',
                "yield": 27,
            },
            {
                "crop": 'Maize',
                "yield": 48,
            }
        ]
    },
    {
        "date": "2020-03-18T00:00:00.000+0000",
        "boundaryStats": [
            {
                "crop": "garlic",
                "yield": 12,
            },
            {
                "crop": "Wheat",
                "yield": 12,
            }
        ]
    },
    {
        "date": "2020-07-18T00:00:00.000+0000",
        "boundaryStats": [{
            "crop": "Onion",
            "yield": 1,
        }
    ]
    }
];
</script>

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386578

You could group with an object and get the values.

var data = [{ date: "2016-07-18T00:00:00.000+0000", boundaryStats: [{ crop: "Wheat", yield: 27 }, { crop: "Maize", yield: 48 }] }, { date: "2020-03-18T00:00:00.000+0000", boundaryStats: [{ crop: "garlic", yield: 12 }, { crop: "Wheat", yield: 12 }] }, { date: "2020-07-18T00:00:00.000+0000", boundaryStats: [{ crop: "Onion", yield: 1 }] }],
    result = Object.values(data.reduce((r, { date, boundaryStats }, i, { length }) => {
        boundaryStats.forEach(({ crop: label, yield: value }) => {
            if (!r[label]) r[label] = { label, data: Array(length).fill(0) };
            r[label].data[i] = value;
        });
        return r;
    }, {}));
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 2

user13705179
user13705179

Reputation:

var data = [
    {
        "date": "2016-07-18T00:00:00.000+0000",
        "boundaryStats": [
            {
                "crop": 'Wheat',
                "yield": 27,
            },
            {
                "crop": 'Maize',
                "yield": 48,
            }
        ]
    },
    {
        "date": "2020-03-18T00:00:00.000+0000",
        "boundaryStats": [
            {
                "crop": "garlic",
                "yield": 12,
            },
            {
                "crop": "Wheat",
                "yield": 12,
            }
        ]
    },
    {
        "date": "2020-07-18T00:00:00.000+0000",
        "boundaryStats": [{
            "crop": "Onion",
            "yield": 1,
        }
    ]
    }
];

 main = [];
data.forEach(e=>{
  e.boundaryStats.forEach((ei,i)=>{    
const checkUsername = obj => obj.label === ei.crop;

    if(!main.some(checkUsername)){
    main.push({
      'label':ei.crop,
      'data': [ei.yield]
      })
    } else {
    let obj = main.find(m => m.label === ei.crop);
    obj.data.push(ei.yield); 
    }
  })
})
console.log(main)

Upvotes: 0

Related Questions