Related
The task is to build a function where it receives an array and a number that will work as a limit. The thing is that it should return an array with the resulting booleans like this:(i.e. [true, false, false]). But I can't figure out how.
I tried using a for loop to stuff an empty array, but it returns just false.
function aperturas(arrayDeIngresosSemanales, cantMinEst) {
for (var i = 0; i < arrayDeIngresosSemanales.length; i++) {
var a = 0;
var arr = arrayDeIngresosSemanales[i];
for (var j = 0; j < arr.length; j++) {
if (arr[j] <= 0) {
a = a + 1;
}
}
if (a >= cantMinEst) {
return true;
} else {
return false;
}
}
}
aperturas([0, 0, 3, 0], [1, 2, 4, 5], [0, 0, -1], 3);
return breaks out of the function - have a result array instead:
function aperturas(arrayDeIngresosSemanales, cantMinEst) {
let result = [];
// ...
if (a >= cantMinEst) {
result.push(true);
}
result.push(false);
}
// ...
return result;
}
You could even remove the if statement:
result.push(a >= cantMinEst);
You shouldn't return immediately after evaluating an array element.
Create a result array and push result of each array's evaluation and return the result.
Also, you aren't calling the function properly. First argument is an array of arrays, you have to call it like aperturas([[0, 0, 3, 0], [1, 2, 4, 5], [0, 0, -1]], 3)
function aperturas(arrayDeIngresosSemanales, cantMinEst) {
// Create an array to store the result.
var result = [];
for (var i = 0; i < arrayDeIngresosSemanales.length; i++) {
var a = 0;
var arr = arrayDeIngresosSemanales[i];
for (var j = 0; j < arr.length; j++) {
if (arr[j] <= 0) {
a = a + 1;
}
}
// Now compare with limit after iterating completely over the array.
if (a >= cantMinEst) {
result.push(true);
} else {
result.push(false);
}
}
// After iterating over all the arrays, return the result.
return result;
}
console.log(aperturas([[0, 0, 3, 0], [1, 2, 4, 5], [0, 0, -1]], 3));
Or, alternatively if you want to use a more semantic JS feature than the for loop, you could keep the return statements but use the map function instead. That would look something like this:
arrayDeIngresosSemanales.map((arr) => {
var a = 0;
for (var j = 0; j < arr.length; j++) {
if (arr[j] <= 0) {
a = a + 1;
}
}
if (a >= cantMinEst) {
return true;
} else {
return false;
}
})
By that same token, you could also replace the inner for loop with a reduce, but that will be left as an exercise for the reader.
I am trying to build logic currently with arrays and data structure. I am trying to implement the logic using for loop
function getRepeatingNumber(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i] === arr[j]) {
return arr[i];
}
}
}
return undefined;
}
getRepeatingNumber([2, 3, 6, 5, 2]);
the above function takes in array and returns a repeated item in the array so in the above case it will return 2. But what if I have an array something like this arr[2,3,3,6,5,2] in this case it should return 3 but as the outer loop has index [0] which is 2 as the reference it will return 2 as the answer.
How to implement a function that returns the first occurrence of the repeated item.
Instead of iterating with j in the part after i, iterate the part before i:
function getRepeatingNumber(arr){
for (var i = 1; i < arr.length; i++) {
for (var j = 0; j < i; j++) {
if (arr[i] === arr[j]) {
return arr[i];
}
}
}
}
console.log(getRepeatingNumber([2,3,3,6,5,2]));
Note that an explicit return undefined is not needed, that is the default behaviour already.
You could also use indexOf to shorten the code a bit:
function getRepeatingNumber(arr){
for (var i = 1; i < arr.length; i++) {
if (arr.indexOf(arr[i]) < i) {
return arr[i];
}
}
}
console.log(getRepeatingNumber([2,3,3,6,5,2]));
You could even decide to make use of find -- which will return undefined in case of no match (i.e. no duplicates in our case):
function getRepeatingNumber(arr){
return arr.find((a, i) => {
if (arr.indexOf(a) < i) {
return true;
}
});
}
console.log(getRepeatingNumber([2,3,3,6,5,2]));
If you do this for huge arrays, then it would become important to have a solution that runs with linear time complexity. In that case, a Set will be useful:
function getRepeatingNumber(arr){
var set = new Set;
return arr.find(a => {
if (set.has(a)) return true;
set.add(a);
});
}
console.log(getRepeatingNumber([2,3,3,6,5,2]));
And if you are into functions of functions, and one-liners, then:
const getRepeatingNumber = r=>(t=>r.find(a=>[t.has(a),t.add(a)][0]))(new Set);
console.log(getRepeatingNumber([2,3,3,6,5,2]));
You need a data structure to keep track of first occurring index.
My recommendation is to use an array to store all the index of repeating numbers. Sort the array in ascending order and return the item at first index from the array.
function getRepeatingNumber(arr){
var resultIndexArr = [];
var count = 0;
var flag = 0;
for(var i=0;i<arr.length;i++)
{
for(var j=i+1;j<arr.length;j++)
{
if(arr[i] === arr[j])
{
flag = 1;
resultIndexArr[count++] = j;
}
}
}
resultIndexArr.sort((a, b) => a - b);
var resultIndex = resultIndexArr[0];
if(flag === 1)
return arr[resultIndex];
else
return;
}
console.log(getRepeatingNumber([2,3,6,5,2])); // test case 1
console.log(getRepeatingNumber([2,3,3,6,5,2])); // test case 2
console.log(getRepeatingNumber([2,5,3,6,5,2])); // test case 3
This will return correct result, but this is not the best solution. The best solution is to store your items in an array, check for each iteration if the item already exists in your array, if it exists then just return that item.
as a javascript dev you should be comfortable wit functional programming & higher-order functions so check the doc to get more understanding of some useful functions: like filter - find - reduce - findIndex map ...
Documentation
Now to answer your question:
at first you should think by step :
Get the occurrence of an item in an array as function:
const arr = [2, 5, 6, 2, 4, 5, 6, 8, 2, 5, 2]
const res = arr.reduce((numberofOcc, item) => {
if (item === 2)
numberofOcc++
return numberofOcc
}, 0);
console.log(`result without function ${res}`);
/* so my function will be */
const occurenceFun = (num, arr) => {
return arr.reduce((numberofOcc, item) => {
if (item === num)
numberofOcc++
return numberofOcc
}, 0);
}
console.log(`result using my function ${occurenceFun(2, arr)}`);
Now i have this function so i can use it inside another function to get the higher occurrence i have in an array
const arr = [1, 2, 5, 6, 8, 7, 2, 2, 2, 10, 10, 2]
const occurenceFun = (num, arr) => {
return arr.reduce((numberofOcc, item) => {
if (item === num)
numberofOcc++
return numberofOcc
}, 0);
}
/*let's create our function*/
const maxOccurenceFun = arr => {
let max = 0;
arr.forEach(el => {
if (max < occurenceFun(el, arr)) {
max = el
}
})
return max;
}
console.log(`the max occurence in this array is : ${maxOccurenceFun(arr)}`);
This is one of freecodecamps challenges it passes the for loop inside the filter passes the first element of the array newArg but doesn't for the second one and so on therefore the challenge doesn't pass can someone explain to me why. Please don't write any full solutions as i just want a little help to move forward.
function destroyer(arr) {
// Remove all the values
var newArg = [];
for (var i=1; i < arguments.length; i++){
newArg.push(arguments[i]);
}
var newArray = arr.filter(function(val){
for (i = 0; i < newArg.length; i++) {
return val !== newArg[i];
}
});
return newArray;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
The filter call:
var newArray = arr.filter(function(val){
for (i = 0; i < newArg.length; i++) {
return val !== newArg[i];
}
});
is the same as:
var newArray = arr.filter(function(val) {
return val !== newArg[0];
});
because you are returning from the very first iteration.
Solution:
You'll have to wrap the return statement in an if like this:
var newArray = arr.filter(function(val){
for (i = 0; i < newArg.length; i++) {
if(val === newArg[i]) { // don't return if val !== newArg[i]
return true; // return only when they're ===
}
}
return false; // default return (nothing is found in the array)
});
Or use an alternative such as Array.prototype.some like this:
var newArray = arr.filter(function(val){
return newArg.some(function(arg) { // return true if some item pass the test (false otherwise)
return arg === val; // the test
})
});
Not sure how to explain this. I'll try it with an example.
For example, I use the following function as a short for a for loop over an array:
function forEach(array, f) {
var len = array.length, i;
for (i = 0; i < len; i += 1) {
f(i, array[i], len);
}
};
I guess this is not too uncommon. But it leads to problems when replacing the following for loop within a function:
function test(someArray) {
for (var i = 0; i < someArray.length; i++) {
if (someArray[i] === 23) {
return true;
}
}
return false;
}
The replacement:
function test(someArray) {
forEach(someArray, function(i, value) {
if (value === 23) {
return true;
}
});
return false;
}
Does not return the function test when 23 is reached and returns true but keeps executing the statements after the forEach and returns false.
First of all, please use for a callback the same style as in the API for array. Then use the callback as check and leave the decision to the calling function to use the information.
In this case the callback looks for a number and return true if the element is equal to 23. The calling function stops the iteration when receiving true and return true. Otherwise the iteration goes on and if not found, the return value is false.
function forEach(array, f) {
var len = array.length,
i;
for (i = 0; i < len; i ++) {
if (f(array[i], i, array)) {
return true;
}
}
return false;
}
var cb = function (v) { console.log('value', v); return v === 23; };
console.log('result', forEach([1, 2, 3, 4, 5, 23, 6, 7], cb));
console.log('result', forEach([1, 2, 3, 4, 5, 6, 7, 33], cb));
.as-console-wrapper { max-height: 100% !important; top: 0; }
For a different approach, like to get a value back, I suggest to return the item instead of a boolean value. If not found, return undefined.
function forEach(array, f) {
var len = array.length,
i;
for (i = 0; i < len; i ++) {
if (f(array[i], i, array)) {
return array[i];
}
}
}
var cb = function (v) { console.log('value', v); return v === 23; };
console.log('result', forEach([1, 2, 3, 4, 5, 23, 6, 7], cb));
console.log('result', forEach([1, 2, 3, 4, 5, 6, 7, 33], cb));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Your forEach() function needs to return a value. Otherwise of course you will always return false after calling forEach().
function forEach(array, f) {
var len = array.length, i;
for (i = 0; i < len; i += 1) {
if (f(i, array[i], len)) {
return true;
}
}
return false;
};
function test(someArray) {
return forEach(someArray, function(i, value) {
return value == 23;
});
}
There are several ways of achieving the effect. This is a simple one:
function test(someArray) {
var result = false
forEach(someArray, function(i, value) {
if (value == 23) result = true;
});
return result;
}
Note that value should be compared with ==. A single = is for assignment, it just replaces value.
The disadvantage of using forEach here is that the loop won't stop when value is 23. It will finish interating through all the items, even if 23 is the first on the list. With the for-return combo, iteration stops as soon as 23 is found.
If this worries you, there's a trick or two for stopping forEach, but the for-return approach is cleaner.
This question already has answers here:
Remove duplicate values from JS array [duplicate]
(54 answers)
Closed 8 years ago.
I have the following script that's supposed to uniqualize array:
function uniques(arr) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
for (var j = 0; j < arr[i].length; j++) {
if (a.indexOf(arr[i][j]) === -1 && arr[i][j] !== '') {
a.push(arr[i][j]);
}
}
return a;
}
However, when it receives only one element, it just breaks it into the letters (which is understandable).
Do you know how I make it check if it's receiving only one element and then returns it back?
Thanks!
I'm not sure why you need the nested loop - you only need a single loop if you're processing a non-nested array:
function uniques(arr) {
if (arr.length === 1) { return arr };
var a = [];
for (var i = 0, l = arr.length; i < l; i++) {
if (a.indexOf(arr[i]) === -1) {
a.push(arr[i]);
}
}
return a;
}
DEMO
If you want to process nested arrays, use a recursive function. Here I've used underscore's flatten method as the basis:
function toType(x) {
return ({}).toString.call(x).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
}
function flatten(input, output) {
if (!output) { output = []; }
for (var i = 0, l = input.length; i < l; i++) {
var value = input[i];
if (toType(value) !== 'array' && output.indexOf(value) === -1) {
output.push(value);
} else {
flatten(value, output);
}
}
return output.sort(function (a, b) { return a - b; });
};
var arr = [1, 2, 3, [[4]], [10], 5, 1, 3];
flatten(arr); // [ 1, 2, 3, 4, 5, 10 ]
DEMO
I think the solution is this:
function uniques(arr) {
if (arr.length > 1) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
for (var j = 0; j < arr[i].length; j++) {
if (a.indexOf(arr[i][j]) === -1 && arr[i][j] !== '') {
a.push(arr[i][j]);
}
}
return a;
}
else
{
return arr;
}
}
What you're trying to do is a linear search on the created matrix for each item in the original one.
The solution below will accomplish this, but at a great cost. If your original matrix is 50x50 with unique values in each cell, it will take you 50^3 (=125000) loops to exit the function.
The best technique to search, in programming science, takes O(log(N)) that means that if you'll use it on your problem it will take log(50^2) (=11) loops.
function uniques(arr) {
var items = [];
var a = arr.map(function(row, i) {
return row.map(function(cell, j) {
if (items.indexOf(cell) >= 0) {
items.push(cell);
return cell;
}
});
});
}