node_man
node_man

Reputation: 1449

Get count of array objects belonging to a partical ID in JavaScript/Node js

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

Answers (6)

Guillaume Bihet
Guillaume Bihet

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

Apoorv
Apoorv

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

Kunal Mukherjee
Kunal Mukherjee

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

yajiv
yajiv

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

Robby Cornelissen
Robby Cornelissen

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

David Letr&#225;n
David Letr&#225;n

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

Related Questions