Reputation: 1449
I have an array of arrays like this:
var array = [
[ '2','Yes'],
[ '2','Yes'],
[ '2','Yes'],
[ '3','Yes'],
[ '3','Yes'],
[ '4','Yes'],
]
The ID's in the above array (2,3 and 4) come dynamically from a server response. I need to count the number of entries for a particular ID. I'm not able to figure out how to loop over this array to get the expected output. The expected output is:
[{"ID" : "4", Count : "1"},{"ID" : "3", Count : "2"},{"ID" : "2",Count : "3"}]
Note that the output is in the ascending order of the Count.
This is what I tried :
var temp1 = [];
var temp2 = [];
var temp3 = [];
for(var i = 0; i < array.length; ++i){
if(array[i][0] == 2){
temp1.push(array[i])
}
if(array[i][0] == 1){
temp2.push(array[i])
}
if(array[i][0] == 3){
temp3.push(array[i])
}
}
var output = [{
ID: "2",
Count: temp1.length,
},
{
ID: "1",
Count: temp2.length,
},
{
ID: "3",
Count: temp3.length
}]
console.log(output)
I believe the way I'm doing it is not the best approach if the data is dynamic. How do I do it in a better way?
Upvotes: 3
Views: 1097
Reputation: 705
If you want to stick to your for
loop an easy way is to check for each item if it's already included in the output, and if so to increment the count, as such:
var array = [
[ '2','Yes'],
[ '2','Yes'],
[ '2','Yes'],
[ '3','Yes'],
[ '3','Yes'],
[ '4','Yes'],
];
var output = [];
for(var i = 0; i < array.length; ++i) {
if(!output.find(item => item.ID === array[i][0])){
output.push({'ID': array[i][0], 'Count': 1});
} else {
output.find(item => item.ID === array[i][0]).Count += 1;
}
}
output.sort( (a,b) => a.Count - b.Count)
console.log(output);
Upvotes: 0
Reputation: 620
You can get the intended result with the below piece of code as well.
var array = [
[ '2','Yes'],
[ '2','Yes'],
[ '2','Yes'],
[ '3','Yes'],
[ '3','Yes'],
[ '4','Yes'],
]
var arrMap = {}
array.map(item => {
if(arrMap[item[0]]){
arrMap[item[0]]++
}else{
arrMap[item[0]] = 1
}
})
var resultArr = []
for(var keys of Object.keys(arrMap)){
resultArr.push({"ID":keys,"Count":arrMap[keys]})
}
Upvotes: 0
Reputation: 5853
Try using Array#prototype#reduce
const array = [
[ '2','Yes'],
[ '2','Yes'],
[ '2','Yes'],
[ '3','Yes'],
[ '3','Yes'],
[ '4','Yes'],
];
const res = array.reduce((acc, curr) => {
let foundElement = acc.find(x => x.id === curr[0]);
if (!foundElement) {
foundElement = {
id: curr[0],
count: 1
};
acc.push(foundElement);
}
else {
foundElement.count += 1;
}
return acc;
}, [])
.sort((a, b) => a.count - b.count);
console.log(res);
Upvotes: 0
Reputation: 2941
You can try this.
var array = [
[ '2','Yes'],
[ '2','Yes'],
[ '2','Yes'],
[ '3','Yes'],
[ '3','Yes'],
[ '4','Yes'],
];
var y = {};
var z = [];
array.forEach(x=>{ //creating object which will store freq of Id
if(!y[x[0]]){
y[x[0]] = 0;
}
y[x[0]]++;
});
Object.keys(y).forEach(x=>{ //converting above object to array
z.push({'ID': x, 'Count':y[x]});
});
console.log(z.sort((a,b) => a.Count - b.Count))//sorting array as per requirement
Upvotes: 1
Reputation: 97302
Combined use of Array.prototype.reduce()
, Object.entries()
, Array.prototype.sort()
and Array.prototype.map()
will yield this:
const array = [
[ '2','Yes'],
[ '2','Yes'],
[ '2','Yes'],
[ '3','Yes'],
[ '3','Yes'],
[ '4','Yes'],
];
const result = Object.entries(array.reduce((a, [id]) => {
a[id] = (a[id] || 0) + 1;
return a;
}, {})).map(([ID, Count]) => ({ID, Count}))
.sort((a, b) => a.Count - b.Count);
console.log(result);
Upvotes: 7
Reputation: 76
You could use map and filter to transform the array and count the ocurrences, then you sort the array by the count property:
const array = [
[ '2','Yes'],
[ '2','Yes'],
[ '2','Yes'],
[ '3','Yes'],
[ '3','Yes'],
[ '4','Yes'],
];
const result = [];
array.forEach( item => {
if (result.find( id => item[0] === id["ID"])){
return;
}
result.push({"ID": item[0], Count: array.filter(ids => ids[0] === item[0]).length});
})
// And then sort it
result.sort( (a,b) => a.Count - b.Count);
console.log(result);
Upvotes: 1