Use reduce to find number of times an items is in an array. The array could have arrays inside recursively.
var foo = [
1,
[2, 3, 4],
4, [5,6,7], 4
];
bar(foo, 4)
would return 3.
Use reduce to find number of times an items is in an array. The array could have arrays inside recursively.
var foo = [
1,
[2, 3, 4],
4, [5,6,7], 4
];
bar(foo, 4)
would return 3.
-
2
In your example, why would
bar(foo, "a")
return3
, although"a"
occurs only twice in its input? – Codor Commented Dec 30, 2015 at 19:16 - @NorCallKnockOut Thanks for the clarification. – Codor Commented Dec 30, 2015 at 19:21
- foo is not an object, it's an array – edc65 Commented Dec 30, 2015 at 19:22
5 Answers
Reset to default 4Try this one using Array.prototype.reduce
.
var foo = [1, [2, 3, 4], 4, [5, 6, 7], 4];
function f(arr, item) {
return arr.reduce(function (s, i) {
if (Array.isArray(i)) return s+f(i, item);
return s+(i==item?1:0);
}, 0);
}
console.log(f(foo, 4))
The function f
is a recursive function. We loop over all the items and reduce them to one number. The function would be called on all the inner arrays as well, and for the non-array items, we just check them to be equal to the desired item.
You can count all items with one call with Array.prototype.forEach()
The
forEach()
method executes a provided function once per array element.
And a check if the element is an array, then the function is called again with the array as parameter.
var foo = ["a", ["b", "c", "d"], "a"],
object = {};
function count(a, o) {
a.forEach(function (b) {
if (Array.isArray(b)) {
count(b, o);
} else {
o[b] = (o[b] || 0) + 1;
}
})
}
count(foo, object);
document.write('<pre>' + JSON.stringify(object, 0, 4) + '</pre>');
So if you want a recursion (And it'll work in any browser):
var foo = [
"a",
["b", "c", "d"],
"a"
];
function bar(arr, item) {
var count = 0;
if (arr.length == 0) {
return 0;
}
for (var i = 0, l = arr.length; i < l; i++) {
var v = arr[i];
if (typeof v === "string") {
if (v === item) {
count++;
}
} else {
count = count + bar(v, item);
}
}
return count;
}
console.log(bar(foo, "a"));
Here is another functional type of interpretation that doesn't require an external state, although would be more inefficient.
var foo = [
"a",
["b", "c", "d"],
["a", "b"],
"a"
];
function flatten( arr ){
return arr.reduce(function( ret, curr ){
return ret.concat( Array.isArray( curr ) ? flatten( curr ) : [ curr ] );
}, []);
}
function filterBy( arr, val ){
return arr.filter(function( item ){
return item === val;
})
}
console.log( flatten( foo ) );
console.log( filterBy( flatten( foo ), 'a') );
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>
Using underscore you can count number of occurrence of each element with this code:
_.countBy(_.flatten(array), _.identity)
So function foo can be implemented like this:
function bar(foo, element){
return _.countBy(_.flatten(foo), _.identity)[element];
}
var foo = ["a", ["b", "c", "d"], "a"]
console.log(bar(foo, "a"));
Although this solution isn't recursive I find it worth mentioning.