Reputation: 1478
I've got an array of question and different answers (which I build dynamically, so the number of entries and different answers can vary):
var qaArray = [
{ question: "Question", answer: "Answer A"},
{ question: "Question", answer: "Answer B"},
{ question: "Question", answer: "Answer B"},
{ question: "Question", answer: "Answer C"},
{ question: "Question", answer: "Answer A"},
{ question: "Question", answer: "Answer B"},
{ question: "Question", answer: "Answer C"},
{ question: "Question", answer: "Answer A"},
{ question: "Question", answer: "Answer B"},
]
I need a function to build another array object from this, which would hold the 'answer' and 'count', in this case it would be:
[
{ answer: "Answer A", count: 3 },
{ answer: "Answer B", count: 4 },
{ answer: "Answer C", count: 2 },
]
Is there an easy method to do this, without straight forward loops?
Upvotes: 4
Views: 38
Reputation: 2704
You can use Map
to key your answers then reduce
over the data to get counts, like so:
var result = Array.from(qaArray.reduce((acc, { answer }) => {
const current = acc.get(answer) || { answer, count: 0 };
current.count++;
return acc.set(answer, current);
}, new Map()).values());
console.log(result);
Upvotes: 1
Reputation: 6546
You can use reduce
for this. Concept is to push element to accumulator if it doesn't exist and increment the count
if it does.
Please find below solution
var qaArray = [
{ question: "Question", answer: "Answer A"},
{ question: "Question", answer: "Answer B"},
{ question: "Question", answer: "Answer B"},
{ question: "Question", answer: "Answer C"},
{ question: "Question", answer: "Answer A"},
{ question: "Question", answer: "Answer B"},
{ question: "Question", answer: "Answer C"},
{ question: "Question", answer: "Answer A"},
{ question: "Question", answer: "Answer B"},
]
result = qaArray.reduce((acc, item) => {
var exist = acc.find(x => x.answer === item.answer);
if (exist) {
exist.count += 1;
} else {
acc.push({
answer: item.answer,
count: 1
})
}
return acc;
}, []);
console.log(result);
Upvotes: 2
Reputation: 13346
If ES6 is not a problem, it can be done by:
var qaArray = [
{ question: "Question", answer: "Answer A"},
{ question: "Question", answer: "Answer B"},
{ question: "Question", answer: "Answer B"},
{ question: "Question", answer: "Answer C"},
{ question: "Question", answer: "Answer A"},
{ question: "Question", answer: "Answer B"},
{ question: "Question", answer: "Answer C"},
{ question: "Question", answer: "Answer A"},
{ question: "Question", answer: "Answer B"},
];
var result = [...new Set(qaArray.map(q => q.answer))].map(a => ({ answer: a, count: qaArray.filter(e => e.answer === a).length }));
console.log(result);
Upvotes: 3
Reputation: 6364
If you are looking for solution without reduce
or forEach
, here is a verbose way using lodash.
_.countBy
will give you close result, but if you want to transform it into array as you want, use mapValues
.
_.chain(qaArray)
.countBy('answer')
.mapValues(function(value, key) {
return { answer: key, count: value }
})
.values()
.value()
Upvotes: 2