Make a function for a nested for loop - javascript

I want to make a function for a nested for loop in order to avoid having to copy and paste the loop.
I can make a nested for loop into an array so that I only need to copy-paste a single for loop, but that basically means that it takes twice as long to run.
Of course, I can save that array so the function would only need to be called once, but it would be nice if there was a way to send arguments to that function.
I wrote an example for my idea:
function exampleForLoop(num){
let arr = [];
for (let i = 0; i < 2; i++){
for (let j = 0; j < num; j++){
for (let k = 0; k < 3; k++){
arr.push([i,j,k]);
}
}
}
return arr;
}
let exampleArr = exampleForLoop(3);
for (let i = 0; i < exampleArr.length; i++){
console.log(exampleArr[i]);
}
let exampleArr2 = exampleForLoop(1);
for (let i = 0; i < exampleArr2.length; i++){
console.log(exampleArr2[i]);
}

You could go even a step ahead and use a recursive function for the loops along with an array of limits for each loop (starting with zero) and hand over a function which parameters correspond to the looped values.
function loop(limits, fn, values = [], result = []) {
if (!limits.length) {
result.push(fn(...values));
return result;
}
for (let i = 0, l = limits.shift(); i < l; i++) {
loop([...limits], fn, [...values, i], result);
}
return result;
}
loop([2, 3, 3], (...a) => a).forEach(a => console.log(...a));
console.log('');
loop([2, 1, 3], (...a) => a).forEach(a => console.log(...a));
.as-console-wrapper { max-height: 100% !important; top: 0; }

If you make each code that would be in the for loop a separate function, you can send the names of those functions as a parameter of the for loop function, and then you can use functionName(i, j, k) to call them.
Code:
function exampleForLoop(functionName, num){
for (let i = 0; i < 2; i++){
for (let j = 0; j < num; j++){
for (let k = 0; k < 4; k++){
functionName(i, j, k);
}
}
}
}
function exampleFunction1(i, j, k){
console.log(i, j, k);
}
function exampleFunction2(i, j, k){
console.log(i, j, k);
}
exampleForLoop(exampleFunction1, 3);
exampleForLoop(exampleFunction2, 1);

Related

How to make a loop that go up and down at the same time?

i was wandering how to make a loop that go up and down at the same time.
For example, here is the normal loop:
for(let i = 0; i < number.length; i++){}
for(let i = 0; i < number.length; i--){}
How can i simplify this loop?
You can have as many indexes as you want in a for loop:
a = [1,2,3,4,5,6,7]
for (let i = 0, k = a.length - 1; i < a.length && k >= 0; i++, k--) {
console.log(i, k)
}
or, you can compute the second index from the first
a = [1,2,3,4,5,6,7]
for (let i = 0; i < a.length; i++) {
let k = a.length - 1 - i
console.log(i, k)
}
If you want to do that in the modern way, without any indexes at all, this would require some runtime support:
function* iter(a) {
yield* a;
}
function* reversed(a) {
yield* [...a].reverse();
}
function* zip(...args) {
let iters = args.map(iter);
while (1) {
let rs = iters.map(it => it.next());
if (rs.some(r => r.done))
break;
yield rs.map(r => r.value);
}
}
//
a = 'abcdef'
// just like in python!
for (let [x, y] of zip(a, reversed(a)))
console.log(x, y)
You could just embed 2 loops. Such as:
for(let i = 0; i < number.length; i++){ // i going "up"
for(let j = number.length; j > 0; j--){} // j going "down"
}
If you want to get the values from first to the last value and vise versa at the same time you don't have to use double loops. Instead just use the i and arrays length. Here's an example.
var length = number.length - 1
for(let i = 0; i < number.length; i++){
console.log(number[i])
console.log(number[length-i])
}

How do I return a variable from nested For Loops in JavaScript without using a global variable?

Here is my code sans input
// Check if three addends equal sum and return the product if so
let result;
function addNumbers(first,second,third,sum) {
if (first + second + third === sum) {
result = first * second * third;
return (first * second * third);
}
};
// find three numbers in list that add up to specific number
function testResult(list,sum) {
let firstAddend;
let secondAddend;
let thirdAddend;
for (let i = 0; i < list.length; i++) {
firstAddend = list.shift();
for (let j = 0; j < list.length; j++) {
secondAddend = list[j];
for (let k = 1; k < list.length; k++) {
thirdAddend = list[k];
addNumbers(firstAddend,secondAddend,thirdAddend,sum);
}
}
}
};
What I want is testResult() to return the result from addNumbers() when it returns the product. I want to get rid of let result; and result = ... in addNumbers(). I've been confused about scope but I think I'm starting to understand. Does each for loop contain the scope of the previous? If anyone is interested this is from Advent of Code Day 1. I am not certain if having the data is necessary here. If it is let me know and I will edit accordingly.
Does each for loop contain the scope of the previous?
Yes, it does. Whenever you create a sub-scope, all the variables in the previous scope are available. So, you don't actually have to declare firstAddend and secondAddend and thirdAddend ahead of time:
function testResult(list,sum) {
for (let i = 0; i < list.length; i++) {
let firstAddend = list.shift();
for (let j = 0; j < list.length; j++) {
let secondAddend = list[j];
for (let k = 1; k < list.length; k++) {
let thirdAddend = list[k];
addNumbers(firstAddend,secondAddend,thirdAddend,sum);
}
}
}
}
Next, the return means that when you call the function, it takes on the value that you return. So, you don't need a global result variable, as you can just utilize the return value. However, you should move the if statement out of the addNumbers function and into the testResult function, as you need to know when to return, not just what to return. In fact, the addNumbers function is simply enough to where it should just go directly into testResult:
function testResult(list,sum) {
for (let i = 0; i < list.length; i++) {
let firstAddend = list.shift();
for (let j = 0; j < list.length; j++) {
let secondAddend = list[j];
for (let k = 1; k < list.length; k++) {
let thirdAddend = list[k];
if (firstAddend + secondAddend + thirdAddend === sum) {
return firstAddend * secondAddend * thirdAddend;
}
}
}
}
}
For practice, if you want the function, you could do something like the following:
function addNumbers(first,second,third,sum) {
if (first + second + third === sum) {
return (first * second * third);
} else {
return null; // return some value so the calling function knows that no sum was found
}
}
function testResult(list,sum) {
for (let i = 0; i < list.length; i++) {
let firstAddend = list.shift();
for (let j = 0; j < list.length; j++) {
let secondAddend = list[j];
for (let k = 1; k < list.length; k++) {
let thirdAddend = list[k];
let result = addNumbers(firstAddend, secondAddend, thirdAddend, sum);
if (result !== null) {
return result;
}
}
}
}
}

Getting Subset in a functional way

I need to implement a function which gets an array A of n elements and a number k as input, and returns an array with all the subsets of size k of A (each subset will be an array itself).
Define the type of the function, and implement at least 3 tests for the function (using assert). It should be in Javascript/Typescript and functional
For example: FunSubsets ([1,2,3],2) => [[1,2],[1,3],[2,3]]
Any ideas?
You could use a generator function with one more parameter for the temporary result set.
function* subsets(values, size, parts = []) {
var i;
size--;
for (i = 0; i < values.length; i++) {
if (size) {
yield* subsets(values.slice(i + 1), size, [...parts, values[i]]);
} else {
yield [...parts, values[i]];
}
}
}
console.log([...subsets([1, 2, 3], 2)]);
console.log([...subsets([1, 2, 3, 4, 5], 2)]);
.as-console-wrapper { max-height: 100% !important; top: 0; }
loop through the array and for each element you loop again to create a slice with the length k - 1 that you concatenate with the current element of the first loop and you push it to a temporary array that you return in the end.
let myArr = [1, 2, 3, 4];
let k = 2;
function subSet(arr, k) {
let tmpArr = [];
for (var i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
let slice = arr.slice(j, j + k - 1);
slice.push(arr[i]);
tmpArr.push(slice.reverse());
}
}
return tmpArr;
}
let mySubSets = subSet(myArr, k);
console.log(JSON.stringify(mySubSets));

I want to add together the numbers of a nested array

This is what I came up with:
var nestedArr = [[[1,2],[3,4]],[[5,6]]];
function sumTotal() {
for(var i = 0; i < nestedArr.length; i++) {
for(var j = 0; j < nestedArr[i].length; j++) {
for(var k = 0; k < nestedArr[i][j].length; k++) {
var arrNumSum = nestedArr[i][j][k];
arrNumSum += arrNumSum;
return arrNumSum;
}
}
}
}
sumTotal();
You can instead create recursive function using reduce()
var nestedArr = [[[1,2],[3,4]],[[5,6]]];
function sum(arr) {
return arr.reduce(function(r, e) {
return r + (Array.isArray(e) ? sum(e) : e)
}, 0)
}
console.log(sum(nestedArr))
You're overwriting arrNumSum each time through the loop. Moreover, you're returning too soon, right after the first iteration. Try this instead:
var nestedArr = [[[1,2],[3,4]],[[5,6]]];
function sumTotal() {
var arrNumSum = 0;
for(var i = 0; i < nestedArr.length; i++) {
for(var j = 0; j < nestedArr[i].length; j++) {
for(var k = 0; k < nestedArr[i][j].length; k++) {
arrNumSum += nestedArr[i][j][k];
}
}
}
return arrNumSum;
}
console.log(sumTotal());
You could use a recusive call of Array#reduce with a named function as callback.
var array = [[[1, 2], [3, 4]], [[5, 6]]],
total = array.reduce(function add(r, a) {
return Array.isArray(a) ? a.reduce(add, r) : r + a;
}, 0);
console.log(total);

[JS]Array merging without using array functions

I need help merging two arrays without using any of the array built in functions ( no concat, push, pop, shift, replace, sort, splice, etc)
And I've got to this point but I'm stuck.
function addTwoArrays(arr1, arr2){
var merge = [], p;
for(p = 0; p < arr1.length; p++){
merge[arr1[p]] = true;
}
for(p = 0; p < arr2.length; p++){
merge[arr2[p]] = true;
}
return Object.keys(merge);
}
window.alert(addTwoArrays([1,2,3,4],[4,3,2,1]));
return is 1,2,3,4 - instead of 1,2,3,4,4,3,2,1
You only need to loop once - simply take arr1.length as a start index and add to the array:
function addTwoArrays(arr1, arr2) {
let start = arr1.length;
for (let i = 0; i < arr2.length; i++) {
arr1[start++] = arr2[i];
}
return arr1;
}
console.log(addTwoArrays([1, 2, 3, 4], [4, 3, 2, 1]));
Keys are unique in a JSON object. So, Object.keys() will return unique occurrences of each element.
Instead try this:
function addTwoArrays(arr1, arr2){
var merge = [], p, index = 0;
for(p = 0; p < arr1.length; p++){
merge[index++] = arr1[p];
}
for(p = 0; p < arr2.length; p++){
merge[index++] = arr2[p];
}
return merge;
}
window.alert(addTwoArrays([1,2,3,4],[4,3,2,1]));
function mergedArray(arrayOne, arrayTwo) {
let newArr = arrayOne
let x = arrayOne.length
let y = arrayTwo.length
let z = arrayOne.length + arrayTwo.length
let i, j
for (i = x, j = 0; i < z && j < y; i++, j++) {
newArr[i] = arrayTwo[j]
}
return newArr
}

Categories

Resources