I've got an in depth array (arrays of arrays). I'm trying to make a decent function without using any extra methods and JS designs (like closures).
This is a working solution (but a bad one because of the global variable)
var counter = 0;
function findArray(array, item) {
for (var i = 0; i < array.length; i++) {
if (array[i] == item) {
counter++;
} else if (array[i].constructor === Array) {
findArray(array[i], item);
}
}
return counter;
}
This is a none working solution with trying to avoid the global counter variable.
function findArray(array, item, counter) {
for (var i = 0; i < array.length; i++) {
if (array[i] == item) {
++counter;
}
if (array[i].constructor === Array) {
findArray(array[i], item, counter);
}
}
return counter;
}
I would also like to avoid the counter input parameter since parameters should only be inputs and output variables shouldn't be inside the function params. Also I would like to avoid built in methods for instance slice etc.
NOTE: The optimal performance of the algorithm should not be taken into consideration.
Is there a way to make this work with the counter being inside the function?
function call looks like this:
findArray([1,[1,2,3],1,[5,9,1],6], 1,0);
The output should be number 4, in this example (integer 1 is the number to be searched in the array).
This is a use case for recursion. (And also for Array.isArray
, which was added in ES5.) findArray
can call itself to find occurrences within arrays within the array:
function findArray(array, item) {
var counter = 0;
for (var i = 0; i < array.length; i++) {
var entry = array[i];
if (entry == item){
counter++;
} else if (Array.isArray(entry)) {
// Add in the count of occurrences in the array, and any arrays in it
counter += findArray(entry, item);
}
}
return counter;
}
It's also a use case for Array#reduce
:
function findArray(array, item) {
return array.reduce(function(counter, entry) {
if (entry == item) {
++counter;
}
if (Array.isArray(entry)) {
counter += findArray(entry, item);
}
return counter;
}, 0);
}
Array#reduce
calls the callback once per entry in the array, passing in the accumulator on each call. The initial value of the accumulator is provided as a second argument (optional in some cases, but not here); the callback returns an updated version of the accumulator, which is the ultimate return value of reduce
.
You have the right idea. You can modify the first recursive function like this:
function findArray(array, item) {
var occurrences = 0;
for (var i = 0; i < array.length; i++) {
if (array[i] == item) {
// Found an occurrence.
occurrences++;
} else if (array[i].constructor === Array) {
// Add all occurrences in the sub-array i
occurrences += findArray(array[i], item);
}
}
return occurrences;
}
console.log(findArray([1, [1, 2, 3], 1, [5, 9, 1], 6], 1, 0));
Or shorten it using a reduce call, which has the same idea as above:
function findArray(array, item) {
return array.reduce((occur, e) =>
occur + ((Array.isArray(e)) ? findArray(e, item) : (e == item)), 0);
}
console.log(findArray([1, [1, 2, 3], 1, [5, 9, 1], 6], 1, 0));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With