How to aggregate JSON to show a count for each same value

Viewed 609

I have the following data obtained from my server response:

var data = [
    {
        project: {
            name: "KB",
            $type: "Project"
        }
    },
    {
        project: {
            name: "Test",
            $type: "Project"
        }
    },
    {
        project: {
            name: "Test",
            $type: "Project"
        }
    },
    {
        project: {
            name: "KB",
            $type: "Project"
        }
    },
    {
        project: {
            name: "Test",
            $type: "Project"
        }
    },
    {
        project: {
            name: "Test",
            $type: "Project"
        }
    }
];

I need to prepare my data for the following steps. Ideally, I need to get the following output:

var aggregatedData = [
    {
        projectName: "KB",
        count: 2
    },{
        projectName: "Test",
        count: 4
    },
];

Is it possible? If so, what is the best way to implement this using jQuery?

5 Answers

You could do it as follows -

var data = [{
    project: {
      name: "KB",
      $type: "Project"
    }
  },
  {
    project: {
      name: "Test",
      $type: "Project"
    }
  },
  {
    project: {
      name: "Test",
      $type: "Project"
    }
  },
  {
    project: {
      name: "KB",
      $type: "Project"
    }
  },
  {
    project: {
      name: "Test",
      $type: "Project"
    }
  },
  {
    project: {
      name: "Test",
      $type: "Project"
    }
  }
];

var hashMap = {}

data.map(element => {
  // if the key(name) is inserted in our hashmap, just increment the count
  // if the key isn't present, then just assign the count of that key(name) as 1 and increment next time onwards
  hashMap[element.project.name] = hashMap[element.project.name] + 1 || 1;
});

// our count for each name is ready...just getting the result ready in our desired format
var aggregatedData =
  Object.keys(hashMap).map(element =>
    ({
      projectName: element,
      count: hashMap[element]
    })
  )
// And done ... :)
console.log(aggregatedData);

What we are doing in the above approach is creating a variable which will act as out hashmap. It will iterate over the data array and for each element in data array, we are counting the number of occurrences of each unique name.

Lastly, we are iterating over the created hashmap and using the key-value pair stored in hashmap( which are nothing but name-count of occurrences pairs) and using it to get the aggregated data in our desired format.

Using reduce() to create a Map of counts then iterate the Map to generate results

const counts = data.reduce((m,{project:{name:n}}) => m.set(n, (m.get(n)||0)+1), new Map)

const res = [...counts].map(([projectName,count]) => ({projectName,count}));

console.log(res)
<script>
var data=[{project:{name:"KB",$type:"Project"}},{project:{name:"Test",$type:"Project"}},{project:{name:"Test",$type:"Project"}},{project:{name:"KB",$type:"Project"}},{project:{name:"Test",$type:"Project"}},{project:{name:"Test",$type:"Project"}}];
</script>

You can do this. Create an hash map of project name to count. Iterate over each entry in input array and increment the count for that project. And then use map() function to transform all keys into the aggregate data you desire.

var data = [{
    project: {
      name: "KB",
      $type: "Project"
    }
  },
  {
    project: {
      name: "Test",
      $type: "Project"
    }
  },
  {
    project: {
      name: "Test",
      $type: "Project"
    }
  },
  {
    project: {
      name: "KB",
      $type: "Project"
    }
  },
  {
    project: {
      name: "Test",
      $type: "Project"
    }
  },
  {
    project: {
      name: "Test",
      $type: "Project"
    }
  }
];


let obj = {};
data.forEach(d => {
  obj[d.project.name] = obj[d.project.name] || 0;
  obj[d.project.name]++;
});

let aggregatedData = Object.keys(obj).map(k => ({
  projectName: k,
  count: obj[k]
}));
console.log(aggregatedData);

See my comment:

var data = [
    {
        project: {
            name: "KB",
            $type: "Project"
        }
    },
    {
        project: {
            name: "Test",
            $type: "Project"
        }
    },
    {
        project: {
            name: "Test",
            $type: "Project"
        }
    },
    {
        project: {
            name: "KB",
            $type: "Project"
        }
    },
    {
        project: {
            name: "Test",
            $type: "Project"
        }
    },
    {
        project: {
            name: "Test",
            $type: "Project"
        }
    }
];

let newObj = {}

for(let item of data) {
  const {project} = item;
  if(project.name in newObj) {
    newObj[project.name] += 1
  } else {
    newObj[project.name] = 1
  }
}

let resultArray = []

for (let item in newObj) {
  resultArray = [...resultArray, {projectName: item, count: newObj[item]}]
}

console.log(resultArray)

Iterate over the array and look if the projectname is in the indexResult. If not create this index and add an entry for this Result with count 1. Otherwise get in the result this entry and increment the count.

Note: I let the solution open for any count of projectnames not only for the 2 listed KB and Test.

function convert(data) {
    let result = [];
    let indexResult = []; 
    data.forEach(elem => {
         let name = elem.project.name;
         let index = indexResult.indexOf(name);
         if (index === -1) {
             indexResult.push(name);
             result.push({projectName: name, count: 1});
         } else {
             result[index].count++;
         }
    })
    return result;
}

var data = [
    {
        project: {
            name: "KB",
            $type: "Project"
        }
    },
    {
        project: {
            name: "Test",
            $type: "Project"
        }
    },
    {
        project: {
            name: "Test",
            $type: "Project"
        }
    },
    {
        project: {
            name: "KB",
            $type: "Project"
        }
    },
    {
        project: {
            name: "Test",
            $type: "Project"
        }
    },
    {
        project: {
            name: "Test",
            $type: "Project"
        }
    }
];

console.log(convert(data));

Related