0

I have an array of data in the below format

let people=[
  {
    aggregationType: "1",
    coefficient: 0.03,
    id: "p1",
    name: "petter",
    type: "Number",
    age: 14
  },
  {
    aggregationType: "0",
    coefficient: 1,
    id: "p2",
    name: "mary",
    type: "Number",
    value: 24
  },
  {
    aggregationType: "1",
    coefficient: 0.03,
    id: "p1",
    name: "Amee",
    type: "Number",
    value: 32
  },
  {
    aggregationType: "0",
    coefficient: 1,
    id: "p2",
    name: "Mtp",
    type: "Number",
    value: 33
  },
  {
    aggregationType: "1",
    coefficient: 0.03,
    id: "p1",
    name: "Louis",
    type: "Number",
    value: 44
  },
]

I want to grouped the dataset by the 'id' and check the condition: if key aggregationType = 0 then calculate sum age, if key aggregationType = 1 then calculate Avg age. And multiply by key 'coefficient' so that the desired result should be like this.

output=[
  [
    "p1", 0.9  // equivalent to ((14 + 32 + 44)/3)*0.03 aggregationType = 1 ==> calculate avg age,coefficient: 0.03
  ],
  [
    "p2", 57  // equivalent to (24+33)*1 = 57  aggregationType = 0 ==> calculate sum age, coefficient: 1
  ]
]

I tried to write this function but I don't know how to continue.

let result = {};

for ( let { id, aggregationType, value } of task ) 
{ 
  result[id] = result[id] || [];
  result[id].push({aggregationType, value }); 
}
console.log(result);
/*
// group by id
result = {
  p1: [
    {
      aggregationType: "1",
      value: 14
    },
    {
      aggregationType: "1",
      value: 32
    },
    {
      aggregationType: "1",
      value: 44
    }
  ],
  p2: [
    {
      aggregationType: "0",
      value: 24
    },
    {
      aggregationType: "0",
      value: 33
    },
    
  ]
}

*/
let newResult=[];
for (let [key, value] of Object.entries(result)) {
    newResult = [key, value.reduce((a, e) => {
    if (e.aggregationType === '0') {
        a += e.value ;
    } else {
       (a += e.value) / value.length;
    }
     return a;
}, 0)]
}

Please help me, thank you!

3
  • 1
    Did you find an answer acceptable? Commented Aug 18, 2020 at 19:23
  • @trincot Your answer results as I desired. I have not used the set, get in js ever so I will learn more Commented Aug 19, 2020 at 1:42
  • Using a Map (with get, set) is a way to avoid a time complexity of O(n²). When input is very large, this can make a huge difference in performance. Commented Aug 19, 2020 at 6:12

3 Answers 3

1

As you could have more than two distinct id values, I would suggest creating a Map keyed by id where in the corresponding values you store the corresponding aggregation type, coeefficient, and keep track of sum and count.

Then after the accumulation you can extract the values from this Map into the desired output format:

function aggregate(people) {
    let map = new Map;
    for (let {aggregationType, coefficient, id, age} of people) {
        let entry = map.get(id);
        if (!entry) map.set(id, entry = { aggregationType, coefficient, sum: 0, count: 0 });
        entry.sum += age;
        entry.count++;
    }
    return Array.from(map, ([id, { aggregationType, coefficient, sum, count}]) => 
        [id, (+aggregationType ? sum / count : sum) * coefficient]
    );
}

let people=[{aggregationType: "1",coefficient: 0.03,id: "p1",name: "petter",type: "Number",age: 14},{aggregationType: "0",coefficient: 1,id: "p2",name: "mary",type: "Number",age: 24},{aggregationType: "1",coefficient: 0.03,id: "p1",name: "Amee",type: "Number",age: 32},{aggregationType: "0",coefficient: 1,id: "p2",name: "Mtp",type: "Number",age: 33},{aggregationType: "1",coefficient: 0.03,id: "p1",name: "Louis",type: "Number",age: 44},]

console.log(aggregate(people));

Sign up to request clarification or add additional context in comments.

2 Comments

hello sir. What do you mean by code +aggregationType . ([id, (+aggregationType ? sum / count : sum) * coefficient])
The + is the unary plus: it converts its argument to number, so it will be 0 or 1. 0 is falsy, 1 is truthy for the ternary operator, so that means when aggregationType is "1", this will evaluate to sum / count, and when it is "0", just sum.
0

Ciao, you could try to use filter function to filter your people based on aggregation and then use a forEach to calculate result:

let people=[
          {
            aggregationType: "1",
            coefficient: 0.03,
            id: "p1",
            name: "petter",
            type: "Number",
            value: 14
          },
          {
            aggregationType: "0",
            coefficient: 1,
            id: "p2",
            name: "mary",
            type: "Number",
            value: 24
          },
          {
            aggregationType: "1",
            coefficient: 0.03,
            id: "p1",
            name: "Amee",
            type: "Number",
            value: 32
          },
          {
            aggregationType: "0",
            coefficient: 1,
            id: "p2",
            name: "Mtp",
            type: "Number",
            value: 33
          },
          {
            aggregationType: "1",
            coefficient: 0.03,
            id: "p1",
            name: "Louis",
            type: "Number",
            value: 44
          },
        ]
        let result = [];
        let aggregationType = ["0", "1"];  //put here all the aggregation types you need
        aggregationType.forEach(aggregation => {
           let peopleFiltered = people.filter(el => el.aggregationType === aggregation)
           let sum = 0;
           let id = "";
           peopleFiltered.forEach(el => {
              sum = sum + (el.value * el.coefficient);
              id = el.id;
           })
           let partialResult = [];
           if (aggregation === "0") {
              partialResult = [ id, sum ]
           }
           else if(aggregation === "1") {
              partialResult = [ id, sum/peopleFiltered.length ]
           }
// extend this 'if...else if' to add new calculation for different aggregation
           
           result.push(partialResult)
        })

        
        console.log(result)

7 Comments

id p1 and p2 not fixed, i can have p3 p4 .... please help me.. thank u
@oneeyes I updated my answer with a dynamic solution (you have only to add all the aggregation you want to aggregationType array and extend if...esleif with all the aggregation calculations you need)
This solution has a time complexity of O(n²), while it can be done with O(n) time complexity.
@Giovanni Esposito may i ask you more. In case the people array has both aggregationType =1 and = 0, the program is desired . if aggregationType can = 0 or 1 then your program will not run as expected. For example : jsfiddle.net/681gktox/14
@Giovanni Esposito I want in case aggregationType = 0 or =1, which is grouped by p1,p2 and calculations. If remove "0" or "1" in aggregationType array , In case the array people has aggregationtype = 1 and 0, the result is not desired
|
0

let people=[{aggregationType: "1",coefficient: 0.03,id: "p1",name: "petter",type: "Number",value: 14},{aggregationType: "0",coefficient: 1,id: "p2",name: "mary",type: "Number",value: 24},{aggregationType: "1",coefficient: 0.03,id: "p1",name: "Amee",type: "Number",value: 32},{aggregationType: "0",coefficient: 1,id: "p2",name: "Mtp",type: "Number",value: 33},{aggregationType: "1",coefficient: 0.03,id: "p1",name: "Louis",type: "Number",value: 44}];

var data = {};
people.forEach(function(item, index){
    data[item.id] = data[item.id] || {};
    data[item.id]['result'] = data[item.id]['result'] || 0;
    data[item.id]['values'] = data[item.id]['values'] || [];
    data[item.id]['values'].push(item.value)
    if('1' === item.aggregationType) {
        data[item.id]['result'] =  data[item.id]['values'].reduce(function(a,b){ return a + b},0) / data[item.id]['values'].length * item.coefficient;
    } else {
         data[item.id]['result'] = data[item.id]['result'] + item.value
    }

});

console.log(data.p1.result)
console.log(data.p2.result)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.