Can you explain me the JS code ? How its working? - javascript

console.log([1 , 2, 3 , 4 , 5].map((acc = 0 , num => acc += num)));
// output : [1, 3, 6, 10, 15]
I know closure has been applied here to this code but don't know how it's working, step by step - I want to visualize that.
We know the map has this Signature:
array.map(function(currentValue, index, arr), thisValue)
With this can anyone explain the code above to me?

This is technically creating a closure, but the key part is that this is declaring a global variable acc (unless acc already exists in the current scope), initializing it with the value 0, then using that inside the anonymous arrow function. By using the grouping operator and the comma operator, it's done inline.
console.log([1 , 2, 3 , 4 , 5].map((acc = 0 , num => acc += num)));
// output : [1, 3, 6, 10, 15]
console.log(acc, window.acc); // acc exists globally
It's equivalent to this:
acc = 0;
console.log([1 , 2, 3 , 4 , 5].map(num => acc += num));
// output : [1, 3, 6, 10, 15]
console.log(acc, window.acc); // acc exists globally
Note that in strict mode, unless you've declared the variable before, the program will fail.
"use strict";
console.log([1 , 2, 3 , 4 , 5].map((acc = 0 , num => acc += num)));
// output : ReferenceError: Can't find variable: acc
console.log(acc, window.acc); // acc doesn't exist because program exits
"use strict";
let acc;
console.log([1 , 2, 3 , 4 , 5].map((acc = 0 , num => acc += num)));
// output : [1, 3, 6, 10, 15]
console.log(acc, window.acc); // acc doesn't exist globally, but it does locally

Related

From simple array to 2D array using reduce (ft. logical AND &&)

I needed to "convert" a simple flat array into a 2D array and I went on SO to see what it has to say about the argument.
I tried to recreate the code of this answer, and I got this error:
console.log(array.reduce((twoDArray, n, i) => (i % 3 == 0 ? twoDArray.push([n]) : twoDArray[twoDArray.length-1].push(n)), []));
^
TypeError: Cannot read property 'push' of undefined
The problem was that I didn't add && twoDArray at the end of the arrow function. Here you can see:
let array = [1,2,3,4,5,6,7,8,9];
// this works
console.log(array.reduce((twoDArray, n, i) => (i % 3 == 0 ? twoDArray.push([n]) : twoDArray[twoDArray.length-1].push(n)) && twoDArray, []));
// here the second push() throws an error
console.log(array.reduce((twoDArray, n, i) => (i % 3 == 0 ? twoDArray.push([n]) : twoDArray[twoDArray.length-1].push(n)), []));
Now I don't understand a couple of things, namely:
how does this && twoDArray works? what's its purpose?
how can this addition fix the error when it is placed only after the push() that generates the error. Shouldn't the code throw an error before to reach the &&?
This is needed because push returns the new length of the array - but the accumulator needs to be the array, not the length.
Without the &&, and indenting the code into multiple lines to make it clearer what's going on, the second code is equivalent to:
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// here the second push() throws an error
console.log(array.reduce((twoDArray, n, i) => {
return (i % 3 == 0 ? twoDArray.push([n]) : twoDArray[twoDArray.length - 1].push(n))
}, []));
Same as:
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// here the second push() throws an error
console.log(array.reduce((twoDArray, n, i) => {
return (
i % 3 == 0
? twoDArray.push([n])
: twoDArray[twoDArray.length - 1].push(n)
);
}, []));
Now, the problem should be clear: no matter which condition is entered, the callback evaluates to
return (
i % 3 == 0
? someNumber
: someNumber
);
because .push evaluates to the new length of the array.
Adding && twoDArray to it makes the callback look like:
return (
i % 3 == 0
? someNumber
: someNumber
) && twoDArray;
therefore returning twoDArray instead of the number.
Shouldn't the code throw an error before to reach the &&?
It does. The error is thrown on the second iteration, when twoDArray[twoDArray.length-1], when twoDArray is a number, evaluates to undefined, so it can't be pushed to. But the problem that twoDArray is a number instead of an array results from the code at the tail end of the prior (first) iteration: the lack of the && twoDArray;.
Code like this is extremely confusing. Try not to condense code into a single line if it makes it unreadable. Another issue is that .reduce arguably isn't appropriate when the accumulator is the same object on each iteration. Consider instead doing something like this:
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const twoDArray= [];
array.forEach((n, i) => {
i % 3 == 0
? twoDArray.push([n])
: twoDArray[twoDArray.length - 1].push(n);
});
console.log(twoDArray);
And use if/else instead of the conditional operator:
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const twoDArray= [];
array.forEach((n, i) => {
if (i % 3 === 0) twoDArray.push([n])
else twoDArray[twoDArray.length - 1].push(n);
});
console.log(twoDArray);

How to find elements in array JavaScript where array[i] = i?

I need to find elements in an array of numbers where arr[i] === i, meaning the element must be equal to the array index.
They must be found with using recursion, not just by cycle.
I would be very thankful, if someone help, because I've spent many hours and can't do anything.
I've tried to use Binary Search but it doesn't work. In the end I've got only the empty array.
function fixedPointSearch(arr, low, high) {
let middle = Math.floor((high - low) / 2);
console.log( low, high, middle )
let arrRes = [];
if (arr[middle] === middle)
{ arrRes.push(arr[middle]); }
else if (arr[middle] > middle)
{ fixedPointSearch(arr, middle + 1, high); }
else
{ fixedPointSearch(arr, low, middle - 1); }
return arrRes;
}
const arr1 = [-10, -3, 2, 3, 6, 7, 8, 9, 10, 12, 16, 17];
console.log(fixedPointSearch(arr1, 0, arr1.length - 1));
To do this recursively, you presumably want to recurse on smaller and smaller arrays, but that means you need to also update the index you're checking on each call. One of the simplest ways to do this is just to include an index in the parameters to your function and increment it on each recursive call. This is one way to do so:
const fixedPointSearch = ([x, ...xs] = [], index = 0) =>
x == undefined
? []
: [... (x === index ? [x] : []), ... fixedPointSearch (xs, index + 1)]
console .log (
fixedPointSearch([-10, -3, 2, 3, 6, 7, 8, 9, 10, 12, 16, 17])
)
It's debatable whether that version or the following one is easier to read, but they are doing essentially the same thing:
const fixedPointSearch = ([x, ...xs] = [], index = 0) =>
x == undefined
? []
: x === index
? [x, ... fixedPointSearch (xs, index + 1)]
: // else
fixedPointSearch (xs, index + 1)
There is a potential problem, though. Running this over a large array, we could hit the recursion depth limit. If the function were tail-recursive, that problem would simply vanish when JS engines perform tail-call optimization. We don't know when that will be, of course, or even it it will actually ever happen, even though it's been specified for five years. But it sometimes makes sense to write to take advantage of it, on the hope that it will one day become a reality, especially since these will still work as well as the non-tail-call version.
So a tail-recursive version might look like this:
const fixedPointSearch = ([x, ...xs] = [], index = 0, res = []) =>
x == undefined
? res
: fixedPointSearch (xs, index + 1, x === index ? [...res, x] : res)
You can solve this w/o additional temporary arrays and parameters, by simply shortening the array in each step:
const myArray = [0, 5, 2, 4, 7, 9, 6];
function fixedPointSearch(arrayToTest) {
if (arrayToTest.length === 0) {
return [];
}
const lastIndex = arrayToTest.length - 1;
const lastItem = arrayToTest[lastIndex];
const remainingItems = arrayToTest.slice(0, lastIndex);
return lastItem === lastIndex
? [...fixedPointSearch(remainingItems), lastItem]
: fixedPointSearch(remainingItems);
}
console.log(fixedPointSearch(myArray));
If you want to find all the elements you should start from the beginning of the array, not the middle and loop through all the indexes.
The idea is for the recursion is to define the end condition.
Then you check if arr[i] === i to update the results array.
Then you make the recursive call with the index incremented and with the updated results array.
function fixedPointSearch(arr, i, results) {
// End condition of the recursion
if (i === arr.length - 1 || arr.length === 0) {
return results;
}
if (arr[i] === i) {
results.push(i);
}
// Recursive call
return fixedPointSearch(arr, i + 1, results);
}
const arr1 = [-10, -3, 2, 3, 6, 7, 8, 9, 10, 12, 16, 17];
console.log(fixedPointSearch(arr1, 0, []));
console.log(fixedPointSearch([], 0, []));
console.log(fixedPointSearch([9, 8, 7], 0, []));
The idiomatic solution in JavaScript uses Array.prototype.filter -
const run = (a = []) =>
a.filter((x, i) => x === i)
console.log(run([ 0, 1, 2, 3, 4, 5 ])) // [0,1,2,3,4,5]
console.log(run([ 3, 3, 3, 3, 3, 3 ])) // [3]
console.log(run([ 7, 1, 7, 3, 7, 5 ])) // [1,3,5]
console.log(run([ 9, 9, 9, 9, 9, 9 ])) // []
Above it should be clear that recursion isn't required for the job. But there's nothing stopping you from using it, if you wish -
const filter = (test = identity, a = [], i = 0) =>
{ /* base */
if (i >= a.length)
return []
/* inductive: i is in bounds */
if (test(a[i], i))
return [ a[i], ...filter(test, a, i + 1) ]
/* inductive: i is in bounds, a[i] does not pass test */
else
return filter(test, a, i + 1)
}
const run = (a = []) =>
filter((x, i) => x === i, a)
console.log(run([ 0, 1, 2, 3, 4, 5 ])) // [0,1,2,3,4,5]
console.log(run([ 3, 3, 3, 3, 3, 3 ])) // [3]
console.log(run([ 7, 1, 7, 3, 7, 5 ])) // [1,3,5]
console.log(run([ 9, 9, 9, 9, 9, 9 ])) // []
For recursion, you'll need an end condition. Something like
const findElementValueIsPositionInarray = arr => {
let results = [];
const find = i => {
if (arr.length) { // as long as arr has values
const value = arr.shift(); // get value
results = i === value // check it
? results.concat(value)
: results;
return find(i+1); // redo with incremented value of i
}
return results;
};
return find(0);
}
console.log(findElementValueIsPositionInarray([2,3,4,3,9,8]).join());
console.log(findElementValueIsPositionInarray([2,3,4,91,9,8]).join());
console.log(findElementValueIsPositionInarray([0,1,2,87,0,5]).join());
.as-console-wrapper { top: 0; max-height: 100% !important; }
I don't know why you want it through recursion:-
But anyway following should help you:-
let ans = [];
function find(arr,index,ans)
{
if(index==arr.length-1)
{
if(arr[index]==index){
ans.push(arr[index])
}
return;
}
if(arr[index]==index){
ans.push(arr[index])
}
find(arr,index+1,ans);
}
const arr1 = [-10, -3, 2, 3, 6, 7, 8, 9, 10, 12, 16, 17];
find(arr1,0,ans);
console.log(ans);

A question on JavaScript .reduce method's accumulator

I was working on this problem to create a function using a reduce method that will get the max number in an array.
The instructor's answer is:
const numbers = [1, 2, 3, 4, 4, 5, 1, 3, 4];
const max = getMax(numbers);
console.log(max);
function getMax(array) {
if (array.length === 0) return undefined;
return array.reduce((accumulator, current) => {
return (accumulator > current) ? accumulator : current
});
I tried something like this:
return array.reduce((accumulator, current) => {
if (accumulator < current)
console.log(accumulator, current);
return accumulator = current;
});
I added console.log (accumulator, current) because I wanted to see what's going on with my code. The log shows as follows:
console.log of my code
1 2
2 3
3 4
4 5
1 3
3 4
4
Question 1. I'd like to know why my function didn't give the right output (it returned 4, not the correct output 5). Shouldn't "accumulator" stay 5 when it is assigned as 5 during the loop?
Question 2. Why do I need to return (or add return in front of) array in the function, when there is already a return below the if statement?
You didn't use { ... } after your if statement, so only the first line console.log(...) is happening when the condition is met. The accumlator = current line always happens for each iteration. You must use return when using imperative style if statement. However you can skip return when using functional style expressions, ie (accumulator, current) => accumulator < current ? current : accumulator which says "if accumulator is less than current, return current, else return accumulator".
Consider this decomposed program. When we see max as an independent function, it helps us see precisely the type of function reduce is expecting -
const max = (a = 0, b = 0) =>
a < b // if a is less than b
? b // return b
: a // otherwise return a
const getMax = (numbers = []) =>
numbers.length === 0 // if numbers.length is zero
? undefined // return undefined
: numbers.reduce(max) // otherwise return reduction
console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5
console.log(getMax([]))
// undefined
console.log(getMax())
// undefined
We can see reduce is produces the following computation -
// given
[1, 2, 3, 4, 4, 5, 1, 3, 4]
// starting with the first two
r = max(1, 2)
// then the next number
r = max(r, 3)
// then the next number
r = max(r, 4)
// then the next number
r = max(r, 4)
Or without intermediate r = ... -
max(max(max(max(max(max(max(max(1, 2), 3), 4), 4), 5), 1), 3), 4)
We could write getMax without reduce, if we wanted -
const max = (a = 0, b = 0) =>
a < b
? b
: a
const getMax = (numbers = []) =>
numbers.length === 0 // without any numbers,
? undefined // there can be no max.
: numbers.length === 1 // if we only have one,
? numbers[0] // we already know max.
: max(numbers[0], getMax(numbers.slice(1))) // else
console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5
console.log(getMax([]))
// undefined
console.log(getMax())
// undefined
Or maybe you haven't learned slice yet. You can use an array index, i, to step thru your array -
const max = (a = 0, b = 0) =>
a < b
? b
: a
const getMax = (numbers = [], i = 0) =>
numbers.length === 0 // without any numbers,
? undefined // there can be no max.
: i + 1 >= numbers.length // if the next i is not in bounds,
? numbers[i] // this is the last number
: max(numbers[i], getMax(numbers, i + 1)) // else
console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5
console.log(getMax([]))
// undefined
console.log(getMax())
// undefined
Destructuring assignment can be used as well -
const max = (a = 0, b = 0) =>
a < b
? b
: a
const getMax = ([ num, ...more ] = []) =>
more.length === 0
? num
: max(num, getMax(more))
console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5
console.log(getMax([]))
// undefined
console.log(getMax())
// undefined
This might show you how you can invent your own reduce -
const max = (a = 0, b = 0) =>
a < b
? b
: a
const reduce = (f, a = [], i = 0) =>
a.length === 0 // without any numbers,
? undefined // there can be no reduction.
: i + 1 >= a.length // if the next i is not in bounds,
? a[i] // this is the last element
: f(a[i], reduce(f, a, i + 1)) // else
const getMax = (numbers = []) =>
reduce(max, numbers) // <-- our reduce!
console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5
console.log(getMax([]))
// undefined
console.log(getMax())
// undefined
Try use Math.max method:
const numbers = [1, 2, 3, 4, 4, 5, 1, 3, 4]
numbers.reduce((acc, rec) => Math.max(acc, rec))
//5
or
function max(numbers) {
return list.reduce((acc, rec) => acc > rec ? acc : rec)
}
if you need find max value without Math.max.

Currying a flipped function using lodash - Are there limitations?

I'm new to lodash and just playing around with it to become familiar.
I'm trying to curry a flipped function and I'm getting a TypeError.
Currying the same 'unflipped' function works as expected.
const curriedMap = _.curry(_.map);
const squares1 = curriedMap([ 1, 2, 3, 4 ]);
console.log(squares1(x => x * x)); // [ 1, 4, 9, 16 ]
const flippedMap = _.flip(_.map);
console.log(flippedMap(x => x * x, [1, 2, 3, 4])); // [ 1, 4, 9, 16 ]
const curriedFlippedMap = _.curry(flippedMap);
const makeSquares = curriedFlippedMap(x => x * x);
console.log(makeSquares([1, 2, 3, 4])); // TypeError: makeSquares is not a function
I'm expecting the last line to produce [ 1, 4, 9, 16 ], but instead I get 'TypeError'. What am I doing wrong?
_.map has a length property (number of parameters) that _.curry can use to curry it automatically, but _.flip(_.map) can’t easily produce a new function with the same length as its input (it reverses the entire argument list, it’s not just f => (a, b) => f(b, a)).
> _.map.length
2
> _.flip(_.map).length
0
_.curry lets you specify the number of parameters to work around that:
const curriedFlippedMap = _.curry(flippedMap, 2);

counting number of occurrences in an array [duplicate]

I have an array:
[1, 2, 3, 5, 2, 8, 9, 2]
I would like to know how many 2s are in the array.
What is the most elegant way to do it in JavaScript without looping with for loop?
[this answer is a bit dated: read the edits, in the notion of 'equal' in javascript is ambiguous]
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)
or as a commenter kindly pointed out:
[....].reduce((total,x) => total+(x==2), 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.
Modern JavaScript:
Note that you should always use triple equals === when doing comparison in JavaScript (JS). The triple equals make 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 ensure that you 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
// Filter all elements equal to 2 and return the length (count)
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 it includes a check for undefined, if you only use double equals as in this case.
Very simple:
var count = 0;
for(var i = 0; i < array.length; ++i){
if(array[i] == 2)
count++;
}
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);
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 ]
]
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
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 ;-)
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
*/
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)
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);
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)
}
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
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
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);
}
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.
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 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
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
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.
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, …}
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);
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
There are many ways to find out. I think the easiest way is to use the array filter method which is introduced in es6.
function itemCount(array, item) {
return array.filter(element => element === item).length
}
const myArray = [1,3,5,7,1,2,3,4,5,1,9,0,1]
const items = itemCount(myArray, 1)
console.log(items)
Something a little more generic and modern (in 2022):
import {pipe, count} from 'iter-ops';
const arr = [1, 2, 3, 5, 2, 8, 9, 2];
const n = pipe(arr, count(a => a === 2)).first; //=> 3
What's good about this:
It counts without creating a new array, so it is memory-efficient
It works the same for any Iterable and AsyncIterable
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
I believe you can use the new Set array method of JavaScript to have unique values.
Example:
var arr = [1, 2, 3, 5, 2, 8, 9, 2]
var set = new Set(arr);
console.log(set);
// 1,2,3,5,8,9 . We get unique values as output.
You can use length property in JavaScript array:
var myarray = [];
var count = myarray.length;//return 0
myarray = [1,2];
count = myarray.length;//return 2

Categories