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