N nested iterations - javascript

I have an array with N objects
var test = [obj1, objc2, ..., objN]
The object is in this format
{"Key", "number", "Name" : "string", "OtherFields" : "Data"}
I want to iterate like this
for (var i = 0; i < test.length; i++) {
for (var j = 1; j < test.length; j++) {
for (var k = 2; k < test.length; k++) {
console.log(test[i].Name + test[j].Name + test[k].Name)
}
}
}
How can i achieve this result for n objects in the array ?
Example:
I have arrays [1, 2, 3, 4] , [2,4,5], [1,2]
i want to get this result:
1 2 1
1 2 2
1 4 1
1 4 2
1 5 1
1 5 2
.....
.....
4 5 2
Those arrays are not always 3 but can be any number >= 2

If I understand correctly, you want permutations.
Here is a recursive approach:
function perm(test, max_depth, depth, s){
if(depth === undefined)
depth = max_depth;
if(s === undefined)
s = '';
if(depth == 0)
console.log(s);
for(var i=depth; i<test.length;i++){
perm(test, max_depth, depth-1, s + test[i].Name);
}
}

var N = 10;
var n = 3;
var test = [];
for (var i = 0; i < N; i++) {
test.push({"Name" : "obj" + i});
}
function log_name_combinations(a, n) {
function nestedlog(a, maxlvl, lvl, s) {
if (lvl < maxlvl) {
for (var i = lvl; i < a.length; i++) {
nestedlog(a, maxlvl, lvl+1, s + a[i].Name);
}
} else {
console.log(s);
}
}
nestedlog(a, n, 0, "");
}
log_name_combinations(test, n);
Demo at JsFiddle
PS: Why are you starting the ith level iteration at the ith index?

Related

JS: Given an array, find element pairs whose sum equal the target value

Yes, as the title suggests
Given an array arr, find element pairs whose sum equal the second argument arg and return the sum of their indices.
What I have done so far
function pairwise(arr, arg) {
if (arr.length === 0) return 0
let res = [];
let indexes = [];
let indexArr = []
for (let i = 0; i < arr.length - 1; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arg === arr[i] + arr[j] && !indexes.includes(i) && !indexes.includes(j)) {
res.push([arr[i], arr[j]]);
indexes.push(i);
indexes.push(j);
}
}
}
console.log(res)
for (let i = 0; i < res.length; i++) {
for (let j = 0; j < res[i].length; j++) {
indexArr.push(arr.indexOf(res[i][j]))
}
}
return indexArr.reduce((curr, prev) => curr + prev)
}
pairwise([1, 1, 1], 2);
I am doing this in Freecodecamp. It passes some test but fails the following tests:
pairwise([1, 1, 1], 2) should return 1. (above code returns 0)
pairwise([0, 0, 0, 0, 1, 1], 1) should return 10. (above code returns 8)
I think I am doing wrong in the indexOf part. How to solve this?

Common Multiple With For Loop

I want to get the common multiple in any given array, the problem i think is in my loop condition i dont want j to be less than 30, i want j to keep multiplying until the common multiple is found you can see the desired output down, how can i do this? thanks in advance.
function m(arr){
for(let i = 0; i < arr.length; i++){
console.log(`when arr[i] = `, i);
for(let j = arr[arr.length - 1]; j < 30; j += arr[arr.length - 1]) {
if(j % arr[i] === 0) console.log(j)
}
}
}
m([2,3,4,5])
this code outputs:
when arr[i] = 2
10
20
when arr[i] = 3
15
when arr[i] = 4
20
when arr[i] = 5
5
10
15
20
25
desired output
when arr[i] = 2
60
when arr[i] = 3
60
when arr[i] = 4
60
when arr[i] = 5
60
According to #Prosy Arceno's suggestion extended a little.
Thanks Prosy.
function m(arr) {
let m = multiply( arr )
for (let i = 0; i < arr.length; i++) {
console.log(`when arr[i] = `, i);
for (let j = arr[ arr.length - 1 ] ; j < m ; j++) {
let result = arr.every(function (element) {
return j % element === 0;
});
if (result) { console.log(j); break }
}
}
}
multiply =( arr )=>{
let m = 1
arr.map( element =>{ m = m * element } )
return m
}
m([2, 3, 4, 5 , 18]);
I think that your general approach is a bit problematic. Your inner for loop searches for the first common multiple of your current arr[i] and the last element of the array arr[arr.length-1].
In your example, this boils down to the inner loop logging a 10 because it is the first common multiple of 2 and 5.
There are many ways to solve your problem (see https://en.wikipedia.org/wiki/Least_common_multiple)
You may use every method of Array.
function m(arr) {
for (let i = 0; i < arr.length; i++) {
console.log(`when arr[i] = `, i);
for (let j = arr[ arr.length - 1 ] ; j < 100; j++) {
let result = arr.every(function (element) {
return j % element === 0;
});
if (result) { console.log(j); }
}
}
}
m([2, 3, 4, 5]);
function m(arr) {
for (let i = 0; i < arr.length; i++) {
console.log(`when arr[i] = `, i);
for (let j = 5; j < 100; j++) {
let result = arr.every(function (element) {
return j % element === 0;
});
if (result) console.log(j);
}
}
}
m([2, 3, 4, 5]);

Loop trough array and sum the length

EDITED:
Can someone help me with the problem below further. I have a class and an array inside the class. I want now use a for loop to sum the length of the previous array length, but for each iteration. If i == 1 I want sum the length of arr[0].x.length, If i == 2 I want sum the length of arr[0].x.length+arr[1].x.length, ect. It will be a lot of code to check each iteration.
Is there a simple way to do this? Instead allways use a new line like
if (i == 1) n = n + arr[i-1].x.length;
if (i == 2) n = n + arr[i-1].x.length+arr[i-2].x.length;
if (i == 3) n = n + arr[i-1].x.length+arr[i-2].x.length+arr[i-3].x.length;
function Class() {
var x = [];
}
for (var i = 0; i < 9; i++) {
arr[i] = new Class();
}
I add 4 items to each object.
arr[0].x.push(...)
arr[0].x.push(...)
...
arr[1].x.push(...)
arr[1].x.push(...)
...
var n = 0;
for (var i = 0; i < arr.length; i++) {
if (i == 1) {
n = n + arr[i-1].x.length;
} else if (i == 2) {
n = n + arr[i-1].x.length+arr[i-2].x.length;
} else if (i == 3) {
n = n + arr[i-1].x.length+arr[i-2].x.length+arr[i-3].x.length;
}
// ect.
}
You could use reduce to get a total of all the lengths of your sub-arrays. For example:
const arrs = [[1, 2, 3], [4, 5, 6]];
const sum = arrs.reduce((acc, arr) => acc += arr.length, 0);
console.log(sum);
// 6
Just nest the loop two times: go over the indexes once then go up to that index from 0 in an inner loop:
for (var i = 0; i < arr1.length; i++) {
for(var j = 0; j <= i; j++) {
n = n + arr1[j].length;
}
}
Edit: benvc's answer is what you are looking for if you want to use reduce.
var arr = [[1,2,3], [4,5,6], [7]];
var n = 0;
for (var i = 0; i < arr.length; i++){
n += arr[i].length;
}
console.log(n);

Unable to push a function return in a loop

I have this function which returns an array of prime numbers:
function getPrimeFactors(n) {
var factors = [];
for (i = 2; i <= Math.sqrt(n); i++) {
if (n % i === 0) {
var count = 0;
while (n % i === 0) {
n = n / i;
count++;
}
for (j = 1; j <= count; j++) {
factors.push(i);
}
}
}
if (n !== 1) {
factors.push(n);
}
return factors;
}
var numbers = [2, 3, 4, 5];
var array = [];
I want to get prime factors of all the numbers in the numbers array and push it into a new array (array)
for(i = 0; i < numbers.length; i++) {
array.push(getPrimeFactors(numbers[i]));
}
What am i doing wrong?
As mentioned by Damien Gold in the answer that was deleted, use var in your for-loops to make the variables local and to prevent your 2 functions from interfering with each other.
function getPrimeFactors(n) {
var factors = [];
for (var i = 2; i <= Math.sqrt(n); i++) {
if (n % i === 0) {
var count = 0;
while (n % i === 0) {
n = n / i;
count++;
}
for (var j = 1; j <= count; j++) {
factors.push(i);
}
}
}
if (n !== 1) {
factors.push(n);
}
return factors;
}
And:
var numbers = [2, 3, 4, 5];
var array = [];
for(var i = 0; i < numbers.length; i++) {
array.push(getPrimeFactors(numbers[i]));
}
As a sidenote,
you are pushing arrays into your array instead of adding the values contained in your getPrimeFactors-array. If you instead want to push the resulting numbers into one array, try this:
for(var i=0; i<numbers.length; i++) {
array = array.concat(getPrimeFactors(numbers[i]));
}

Step through K combinations algorithm X steps at a time

I have a function (from Akseli Palén) to calculate combinations of X elements in a given Array that looks like this.
function k_combinations(set, k) {
var i, j, combs, head, tailcombs;
if (k > set.length || k <= 0) { return []; }
if (k == set.length) { return [set]; }
if (k == 1) {
combs = [];
for (i = 0; i < set.length; i++) { combs.push([set[i]]); }
return combs;
}
// Assert {1 < k < set.length}
combs = [];
for (i = 0; i < set.length - k + 1; i++) {
head = set.slice(i, i+1);
tailcombs = k_combinations(set.slice(i + 1), k - 1);
for (j = 0; j < tailcombs.length; j++) {
combs.push(head.concat(tailcombs[j]));
}
}
return combs;
}
It works nicely but when given a large array and/or K value to work with it slows down to the point where the browser tries to stop the script for being unresponsive so what I'm wondering is is it possible to extend this function so it accepts a starting position and maximum number of results to return in one call? That way I could do something like "Displaying results 20-30 out of 100,000". There is a sample form at
http://jsbin.com/ricabomofetu/1/edit?js,output if anyone wants to have a crack.
How about something like this?
function k_combinations(set, k, start_combo, max_results) {
if (start_combo.length !== k)
throw new Error("Starting combination is not of length k!");
var cur = [];
for (var i = 0; i < k; i++) {
var idx = set.indexOf(start_combo[i]);
if (idx === -1)
throw new Error(i + "th element of starting combination isn't in the set!");
if (i > 0 && idx <= cur[i - 1])
throw new Error("Elements of start_combo must be in sorted order!");
cur.push(idx);
}
function subset_from_indices(subset) {
var ret = [];
for (var i = 0; i < subset.length; i++)
ret.push(set[subset[i]]);
return ret;
}
var n = set.length;
var results = [subset_from_indices(cur)];
while (results.length < max_results) {
var inc_idx = k - 1;
while (inc_idx >= 0 && cur[inc_idx] === n - k + inc_idx)
inc_idx--;
if (inc_idx < 0) // no more combinations
return results
cur[inc_idx]++;
for (var i = inc_idx + 1; i < k; i++) {
cur[i] = cur[i - 1] + 1;
}
results.push(subset_from_indices(cur));
}
return results;
}
console.log(k_combinations([1, 2, 3, 4, 5], 3, [1, 3, 4], 4));
// [ [ 1, 3, 4 ], [ 1, 3, 5 ], [ 1, 4, 5 ], [ 2, 3, 4 ] ]

Categories