How to count certain elements in array?
JavascriptJavascript Problem Overview
I have an array:
[1, 2, 3, 5, 2, 8, 9, 2]
I would like to know how many 2
s are in the array.
What is the most elegant way to do it in JavaScript without looping with for
loop?
Javascript Solutions
Solution 1 - Javascript
[this answer is a bit dated: read the edits]
Say hello to your friends: map
and filter
and reduce
and forEach
and every
etc.
(I only occasionally write for-loops in javascript, because of block-level scoping is missing, so you have to use a function as the body of the loop anyway if you need to capture or clone your iteration index or value. For-loops are more efficient generally, but sometimes you need a closure.)
The most readable way:
[....].filter(x => x==2).length
(We could have written .filter(function(x){return x==2}).length
instead)
The following is more space-efficient (O(1) rather than O(N)), but I'm not sure how much of a benefit/penalty you might pay in terms of time (not more than a constant factor since you visit each element exactly once):
[....].reduce((total,x) => (x==2 ? total+1 : total), 0)
(If you need to optimize this particular piece of code, a for loop might be faster on some browsers... you can test things on jsperf.com.)
You can then be elegant and turn it into a prototype function:
[1, 2, 3, 5, 2, 8, 9, 2].count(2)
Like this:
Object.defineProperties(Array.prototype, {
count: {
value: function(value) {
return this.filter(x => x==value).length;
}
}
});
You can also stick the regular old for-loop technique (see other answers) inside the above property definition (again, that would likely be much faster).
2017 edit:
Whoops, this answer has gotten more popular than the correct answer. Actually, just use the accepted answer. While this answer may be cute, the js compilers probably don't (or can't due to spec) optimize such cases. So you should really write a simple for loop:
Object.defineProperties(Array.prototype, {
count: {
value: function(query) {
/*
Counts number of occurrences of query in array, an integer >= 0
Uses the javascript == notion of equality.
*/
var count = 0;
for(let i=0; i<this.length; i++)
if (this[i]==query)
count++;
return count;
}
}
});
You could define a version .countStrictEq(...)
which used the ===
notion of equality. The notion of equality may be important to what you're doing! (for example [1,10,3,'10'].count(10)==2
, because numbers like '4'==4 in javascript... hence calling it .countEq
or .countNonstrict
stresses it uses the ==
operator.)
> Caveat:
> Defining a common name on the prototype should be done with care. It is fine if you control your code, but bad if everyone wants to declare their own [].count
function, especially if they behave differently. You may ask yourself "but .count(query)
surely sounds quite perfect and canonical"... but consider perhaps you could do something like [].count(x=> someExpr of x)
. In that case you define functions like countIn(query, container)
(under myModuleName.countIn
), or something, or [].myModuleName_count()
.
Also consider using your own multiset data structure (e.g. like python's 'collections.Counter
') to avoid having to do the counting in the first place. This works for exact matches of the form [].filter(x=> x==???).length
(worst case O(N) down to O(1)), and modified will speed up queries of the form [].filter(filterFunction).length
(roughly by a factor of #total/#duplicates).
class Multiset extends Map {
constructor(...args) {
super(...args);
}
add(elem) {
if (!this.has(elem))
this.set(elem, 1);
else
this.set(elem, this.get(elem)+1);
}
remove(elem) {
var count = this.has(elem) ? this.get(elem) : 0;
if (count>1) {
this.set(elem, count-1);
} else if (count==1) {
this.delete(elem);
} else if (count==0)
throw `tried to remove element ${elem} of type ${typeof elem} from Multiset, but does not exist in Multiset (count is 0 and cannot go negative)`;
// alternatively do nothing {}
}
}
Demo:
> counts = new Multiset([['a',1],['b',3]])
Map(2) {"a" => 1, "b" => 3}
> counts.add('c')
> counts
Map(3) {"a" => 1, "b" => 3, "c" => 1}
> counts.remove('a')
> counts
Map(2) {"b" => 3, "c" => 1}
> counts.remove('a')
Uncaught tried to remove element a of type string from Multiset, but does not exist in Multiset (count is 0 and cannot go negative)
sidenote: Though, if you still wanted the functional-programming way (or a throwaway one-liner without overriding Array.prototype), you could write it more tersely nowadays as [...].filter(x => x==2).length
. If you care about performance, note that while this is asymptotically the same performance as the for-loop (O(N) time), it may require O(N) extra memory (instead of O(1) memory) because it will almost certainly generate an intermediate array and then count the elements of that intermediate array.
Solution 2 - Javascript
Modern JavaScript:
Note that you should always use triple equals ===
when doing comparison in JavaScript (JS). The triple equals makes sure, that JS comparison behaves like double equals ==
in other languages (there is one exception, see below). The following solution shows how to solve this the functional way, which will never have out of bounds error
:
// Let has local scope
let array = [1, 2, 3, 5, 2, 8, 9, 2]
// Functional filter with an Arrow function
array.filter(x => x === 2).length // -> 3
The following anonymous Arrow function (lambda function) in JavaScript:
(x) => {
const k = 2
return k * x
}
may be simplified to this concise form for a single input:
x => 2 * x
where the return
is implied.
Always use triple equals: ===
for comparison in JS, with the exception of when checking for nullability: if (something == null) {}
as you include a check for undefined
if you only use double equals, as in this case.
Solution 3 - Javascript
Very simple:
var count = 0;
for(var i = 0; i < array.length; ++i){
if(array[i] == 2)
count++;
}
Solution 4 - Javascript
2017: If someone is still interested in the question, my solution is the following:
const arrayToCount = [1, 2, 3, 5, 2, 8, 9, 2];
const result = arrayToCount.filter(i => i === 2).length;
console.log('number of the found elements: ' + result);
Solution 5 - Javascript
Here is an ES2017+ way to get the counts for all array items in O(N):
const arr = [1, 2, 3, 5, 2, 8, 9, 2];
const counts = {};
arr.forEach((el) => {
counts[el] = counts[el] ? (counts[el] += 1) : 1;
});
You can also optionally sort the output:
const countsSorted = Object.entries(counts).sort(([_, a], [__, b]) => a - b);
console.log(countsSorted)
for your example array:
[ [ '2', 3 ],
[ '1', 1 ],
[ '3', 1 ],
[ '5', 1 ],
[ '8', 1 ],
[ '9', 1 ]
]
Solution 6 - Javascript
If you are using lodash or underscore the _.countBy method will provide an object of aggregate totals keyed by each value in the array. You can turn this into a one-liner if you only need to count one value:
_.countBy(['foo', 'foo', 'bar'])['foo']; // 2
This also works fine on arrays of numbers. The one-liner for your example would be:
_.countBy([1, 2, 3, 5, 2, 8, 9, 2])[2]; // 3
Solution 7 - Javascript
Weirdest way I can think of doing this is:
(a.length-(' '+a.join(' ')+' ').split(' '+n+' ').join(' ').match(/ /g).length)+1
Where:
- a is the array
- n is the number to count in the array
My suggestion, use a while or for loop ;-)
Solution 8 - Javascript
Not using a loop usually means handing the process over to some method that does use a loop.
Here is a way our loop hating coder can satisfy his loathing, at a price:
var a=[1, 2, 3, 5, 2, 8, 9, 2];
alert(String(a).replace(/[^2]+/g,'').length);
/* returned value: (Number)
3
*/
You can also repeatedly call indexOf, if it is available as an array method, and move the search pointer each time.
This does not create a new array, and the loop is faster than a forEach or filter.
It could make a difference if you have a million members to look at.
function countItems(arr, what){
var count= 0, i;
while((i= arr.indexOf(what, i))!= -1){
++count;
++i;
}
return count
}
countItems(a,2)
/* returned value: (Number)
3
*/
Solution 9 - Javascript
I'm a begin fan of js array's reduce function.
const myArray =[1, 2, 3, 5, 2, 8, 9, 2];
const count = myArray.reduce((count, num) => num === 2 ? count + 1 : count, 0)
In fact if you really want to get fancy you can create a count function on the Array prototype. Then you can reuse it.
Array.prototype.count = function(filterMethod) {
return this.reduce((count, item) => filterMethod(item)? count + 1 : count, 0);
}
Then do
const myArray =[1, 2, 3, 5, 2, 8, 9, 2]
const count = myArray.count(x => x==2)
Solution 10 - Javascript
Most of the posted solutions using array functions such as filter are incomplete because they aren't parameterized.
Here goes a solution with which the element to count can be set at run time.
function elementsCount(elementToFind, total, number){
return total += number==elementToFind;
}
var ar = [1, 2, 3, 5, 2, 8, 9, 2];
var elementToFind=2;
var result = ar.reduce(elementsCount.bind(this, elementToFind), 0);
The advantage of this approach is that could easily change the function to count for instance the number of elements greater than X.
You may also declare the reduce function inline
var ar = [1, 2, 3, 5, 2, 8, 9, 2];
var elementToFind=2;
var result = ar.reduce(function (elementToFind, total, number){
return total += number==elementToFind;
}.bind(this, elementToFind), 0);
Solution 11 - Javascript
Really, why would you need map
or filter
for this?
reduce
was "born" for these kind of operations:
[1, 2, 3, 5, 2, 8, 9, 2].reduce( (count,2)=>count+(item==val), 0);
that's it! (if item==val
in each iteration, then 1 will be added to the accumulator count
, as true
will resolve to 1
).
As a function:
function countInArray(arr, val) {
return arr.reduce((count,item)=>count+(item==val),0)
}
Or, go ahead and extend your arrays:
Array.prototype.count = function(val) {
return this.reduce((count,item)=>count+(item==val),0)
}
Solution 12 - Javascript
It is better to wrap it into function:
let countNumber = (array,specificNumber) => {
return array.filter(n => n == specificNumber).length
}
countNumber([1,2,3,4,5],3) // returns 1
Solution 13 - Javascript
I believe what you are looking for is functional approach
const arr = ['a', 'a', 'b', 'g', 'a', 'e'];
const count = arr.filter(elem => elem === 'a').length;
console.log(count); // Prints 3
elem === 'a' is the condition, replace it with your own.
Solution 14 - Javascript
Array.prototype.count = function (v) {
var c = 0;
for (let i = 0; i < this.length; i++) {
if(this[i] === v){
c++;
}
}
return c;
}
var arr = [1, 2, 3, 5, 2, 8, 9, 2];
console.log(arr.count(2)); //3
Solution 15 - Javascript
I use this:
function countElement(array, element) {
let tot = 0;
for(var el of array) {
if(el == element) {
tot++;
}
}
return tot;
}
var arr = ["a", "b", "a", "c", "d", "a", "e", "f", "a"];
console.log(countElement(arr, "a")); // 4
Solution 16 - Javascript
Solution by recursion
function count(arr, value) {
if (arr.length === 1) {
return arr[0] === value ? 1 : 0;
} else {
return (arr.shift() === value ? 1 : 0) + count(arr, value);
}
}
count([1,2,2,3,4,5,2], 2); // 3
Solution 17 - Javascript
var arrayCount = [1,2,3,2,5,6,2,8];
var co = 0;
function findElement(){
arrayCount.find(function(value, index) {
if(value == 2)
co++;
});
console.log( 'found' + ' ' + co + ' element with value 2');
}
I would do something like that:
var arrayCount = [1,2,3,4,5,6,7,8];
function countarr(){
var dd = 0;
arrayCount.forEach( function(s){
dd++;
});
console.log(dd);
}
Solution 18 - Javascript
Create a new method for Array class in core level file and use it all over your project.
// say in app.js
Array.prototype.occurrence = function(val) {
return this.filter(e => e === val).length;
}
Use this anywhere in your project -
[1, 2, 4, 5, 2, 7, 2, 9].occurrence(2);
// above line returns 3
Solution 19 - Javascript
Here is a one liner in javascript.
- Use map. Find the matching values
(v === 2)
in the array, returning an array of ones and zeros. - Use Reduce. Add all the values of the array for the total number found.
[1, 2, 3, 5, 2, 8, 9, 2]
.map(function(v) {
return v === 2 ? 1 : 0;
})
.reduce((a, b) => a + b, 0);
The result is 3
.
Solution 20 - Javascript
Depending on how you want to run it:
const reduced = (array, val) => { // self explanatory
return array.filter((element) => element === val).length;
}
console.log(reduced([1, 2, 3, 5, 2, 8, 9, 2], 2));
// 3
const reducer = (array) => { // array to set > set.forEach > map.set
const count = new Map();
const values = new Set(array);
values.forEach((element)=> {
count.set(element, array.filter((arrayElement) => arrayElement === element).length);
});
return count;
}
console.log(reducer([1, 2, 3, 5, 2, 8, 9, 2]));
// Map(6) {1 => 1, 2 => 3, 3 => 1, 5 => 1, 8 => 1, …}
Solution 21 - Javascript
Another approach using RegExp
const list = [1, 2, 3, 5, 2, 8, 9, 2]
const d = 2;
const counter = (`${list.join()},`.match(new RegExp(`${d}\\,`, 'g')) || []).length
console.log(counter)
The Steps follows as below
- Join the string using a comma Remember to append ',' after joining so as not to have incorrect values when value to be matched is at the end of the array
- Match the number of occurrence of a combination between the digit and comma
- Get length of matched items
Solution 22 - Javascript
You can use built-in function Array.filter()
array.filter(x => x === element).length;
var arr = [1, 2, 3, 5, 2, 8, 9, 2];
// Count how many 2 there are in arr
var count = arr.filter(x => x === 2).length;
console.log(count);
Solution 23 - Javascript
One-liner function
const countBy = (a,f)=>a.reduce((p,v,i,x)=>p+!!f(v,i,x), 0)
countBy([1,2,3,4,5], v=>v%2===0) // 2
Solution 24 - Javascript
You can use length property in JavaScript array:
var myarray = [];
var count = myarray.length;//return 0
myarray = [1,2];
count = myarray.length;//return 2
Solution 25 - Javascript
@{
/**/
var x = from z in Model.ListOfFaculty
select z;
}
@foreach (var c in x)
{
<div class="row">
<div class="col-lg-3">
<label>FacultyName :@c.Name </label>
</div>
<div class="col-lg-3">
<label>
Count :@{
var b = from v in Model.ListOfDepartment
where (v.Faculty_id == c.ID)
select v;
}
@b.Count()
</label>
</div>
</div>
}
</div>