Javascript Combination Generator based on N number of objects - javascript

I need to make a function that receives an array and generates all combinations based on N param size. Example:
function comb([1,2],3)
out:
[[1,1,1],
[1,1,2],
[1,2,1],
[1,2,2],
[2,1,1],
[2,1,2],
[2,2,1],
[2,2,2]]
or:
function comb([4,1],2)
out:
[[4,4],
[4,1],
[1,4],
[1,1]]

I found a solution from Nina Scholz
JavaScript - Generating combinations from n arrays with m elements
and i made an adaptation, this is the result:
var result = 0;
function combination(parts,N){
var parts_normalize = []
while (N--) parts_normalize.push(parts)
result = parts_normalize.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));
console.log(result)
}
this is working well but, someone can explain what is happening in this function xD i am totaly lost

Related

Add sum of all numbers in an array and print the final result

please don't kill me right away, because some topics are already here in the forum. I've read and tried a lot. I just don't get any further with my beginner knowledge.
My problem is the following: I have 4 arrays, the length of the arrays can have a different length each time. Now I would like to add the sum of all 4 arrays and get a final result.
I just can't really get any further than I want. Please bear with me and help me.
Here my example :
var MyData = '{"M":[{"M":{"MD":995,"PT":1,"TT":17,"D":0,"TID":44,"T":0,"HW":109,"KD":0,"TA":[4,17,77,17010,84,5,6,6,6,5,"xxxx",0,0,128,6,-1,0,34,[],0],"SD":1187,"OD":117,"SA":[1,65,67,194,187,7,8,7,6,6,"yyyy",0,0,-1,-1,-1,0,95,[],0]},"UM":{"PD":0,"TD":0,"L":{"ID":23,"ID":2,"VIS":14,"N":"bbbb","GD":102,"L":17,"W":1429,"D":113,"SPR":9,"Q":[[1647,1,2,5,-1,[[4,40,[114.0]],[5,46,[74.3]],[18,89,[43.6]],[116,34,[42.2]]],-1,-1,0,-1,-1,3,[1,5,3090,[7222,32,5,310,[[312,46,[11.4]],[311,55,[12.8]],[34,72,[19.7]],[30,28,[8.4]]],0]]],[187,2,2,5,-1,[[1,9,[82.4]],[2,86,[86.3]],[112,67,[28.1]],[19,35,[22.0]]],-1,-1,0,-1,-1,3,[2,6,2970,[7127,32,6,3240,[[311,28,[8.5]],[314,67,[18.7]],[32,83,[17.3]],[315,46,[8.0]]],0]]],[14650745,3,2,5,-1,[[3,97,[116.8]],[6,55,[74.8]],[109,42,[24.8]],[116,65,[67.0]]],-1,-1,0,-1,-1,3,[3,6,3590,[77381,32,6,3130,[[313,33,[6.3]],[310,83,[21.1]],[312,61,[13.8]],[311,36,[9.8]]],0]]],[14673,4,2,5,-1,[[7,82,[16.1]],[115,40,[21.0]],[121,87,[215,871.0]],[112,48,[22.4]]],-1,-1,0,-1,-1,3,[4,6,3570,[72077,32,2,2710,[[312,44,[11.0]],[311,52,[12.3]],[313,37,[6.8]],[38,38,[8.8]]],0]]],[14681483230,5,2,0,0,[[21,[5.0]]],1070,-1,0,630006,-1,2],[14649672824,6,2,15,-1,[[808,82,[47.1]],[811,77,[28.1]],[812,50,[20.0]],[815,35,[18.4]],[20018,100,[1.0]],[20016,7,[2060,12.0,2061,12.0,2062,12.0,2063,12.0,2064,12.0,2065,12.0,2066,12.0,2067,12.0,2068,12.0,148,12.0,2069,12.0,149,12.0,2070,12.0,150,12.0,151,12.0,2071,12.0,2072,12.0,2073,12.0,2074,12.0,2075,12.0,2076,12.0,2077,12.0,2078,12.0,2079,12.0,2020,12.0,2021,12.0,2022,12.0,2023,12.0,2024,12.0,2025,12.0,2026,12.0,2027,12.0,2028,12.0,2029,12.0,2030,12.0,2031,12.0,2032,12.0,2033,12.0,2034,12.0,2035,12.0,2036,12.0,2037,12.0,2038,12.0,2039,12.0]]],-1,-1,0,-1,-1,3,[65,6,3440,[]]]],"IDS":[[10021,1023],[10022,1033]],"SIS":[1033,1009,1040,100253],"AE":[[64,[8.0]],[503,[20.0]],[504,[48.0]],[504,[48.0]],[339,[50.0]],[504,[48.0]],[613,[50.0]],[66,[65.0]],[503,[65.0]],[503,[45.0]],[504,[30.0]],[504,[45.0]],[614,[8.0]],[66,[48.0]],[504,[60.0]],[66,[45.0]],[504,[48.0]],[614,[30.0]],[66,[24.0]]]}},"GA":{"L":[[287,30],[216,2224],[215,744],[298,60],[651,76],[650,90],[649,132],[240,50]],"M":[[287,30],[216,2720],[215,3808],[298,60],[651,48],[650,102],[649,125],[648,179],[240,50]],"R":[[287,30],[216,2968],[298,60],[651,76],[650,90],[649,132],[240,50]],"RW":[[215,2358],[216,433]]},"AST":[390,400],"ATT":0,"SM":0}],"O":[{"OID":8344,"DUM":false,"N":"xrr","E":{"BGT":0,"BGC1":14408394,"BGC2":1644825,"SPT":2,"S1":82,"SC1":144394,"S2":82,"SC2":163,"IS":1},"L":7,"LL":50,"H":3195,"AVZ":180,"CF":3911,"HF":16245,"PRE":13,"SUF":23,"TPX":-1,"MP":459,"R":0,"AID":48,"AR":0,"AN":"drum vv","aee":{"CF":237604,"BGT":7,"BGC1":16825,"BGC2":3012,"BGC3":864,"SPT":23,"S1":2,"SC1":30512,"S2":41,"SC2":164825,"S3":0,"SC3":164825},"RPT":0,"AP":[[0,1007,1062,76,1],[0,1170610,1067,757,4],[0,1211752,1056,755,4],[0,100,1059,72,4],[1,163,710,79,12],[2,16771,809,68,12],[3,2052697,772,504,12]],"VP":[],"SA":0,"VF":0,"PF":1,"RRD":0,"TI":-1},{"OD":1187,"DM":false,"N":"xyz","E":{"BGT":1,"BG1":81264,"BG2":5126,"SPT":1,"S1":82,"S1":16425,"S2":82,"S2":164825,"IS":1},"L":7,"LL":90,"H":6738,"AVP":87345,"CF":4591,"HF":5623,"PRE":13,"SUF":27,"TX":1,"P":8828,"R":0,"AD":88,"AR":7,"AN":"DDR ","aee":{"CF":1878,"BT":2,"BC1":14494,"BG2":1894,"BC3":-1,"SPT":0,"S1":-1,"S1":-1,"S2":-1,"SC2":-1,"S3":-1,"SC3":-1},"RPT":0,"AP":[[0,1417194,675,607,1],[0,2086,795,1180,4],[0,3363161,663,603,4],[0,7164676,769,1179,4],[1,489,490,318,12],[2,208,33,71,12],[3,4347,42,108,12],[4,112,818,61,12]],"VP":[],"A":0,"VF":0,"PF":1,"RD":0,"TI":-1,"RP":-1}]}'
var MyArray = JSON.parse(MyData)
MyArray.M[0].GA.L.forEach(element1 => console.log(element1[1]));
MyArray.M[0].GA.M.forEach(element2 => console.log(element2[1]));
MyArray.M[0].GA.R.forEach(element3 => console.log(element3[1]));
MyArray.M[0].GA.RW.forEach(element4 => console.log(element4[1]));
//So I give myself all the values ​​first.
//If I then use the for loop on one of the arrays, I get the output:
let sum = 0;
MyArray.M[0].GA.L.forEach(element1 => {
const MyArray = [element1[1]];
for (let i = 0; i < MyArray.length; i++) {
sum += MyArray[i];
}
console.log(sum);
})
//output: 30,2254,2998,3058,3134,3224,3356,3406
The number 3406 is the End Result, how can I print only the End result.
If there is another method to add all 4 arrays together at once, it would help me even more.
If possible an example for an array and an example for all 4 together please
you have to do three things: consolidate all the arrays, get the sum of all values, then print it
first, consolidate
const allArrs = [
...MyArray.M[0].GA.L,
...MyArray.M[0].GA.M,
...MyArray.M[0].GA.R,
...MyArray.M[0].GA.RW
]
then, the array method that would help the most here is Array.Reduce
const result = allArrs.reduce((accumulator, currentArray) => {
accumulator += currentArray[1]
return accumulator
}, 0)
then log the result!
As others have pointed out, this type of problem is very well suited for using a functional programming approach, where you simplify the problem by morphing it into a series of atomic operations that have no side-effects.
JavaScript does a great job of implementing the core functional programming methods of map(), filter(), and reduce(). For this problem, the only thing you need is reduce().
The code below could be made smaller and more efficient, but it was written to show each individual step.
const data = JSON.parse(rawData);
// subData is now an object whose members are the arrays you care about
const subData = data.M[0].GA;
// turn that into an array of arrays
const myArrays = Object.values(subData);
// now use reduce() to flatten the array of arrays into a single array with just
// the numbers you want to sum
const myNums = myArrays.reduce((acc, val) => acc.concat(val[1]), []);
// finally, reduce() again to sum the values
const sum = myNums.reduce((acc, val) => acc + val, 0);
console.log(sum);
You're on the right track. Simply move console.log(sum) outside of the final }) so it's not inside any loops.
I hope I understand what you are trying to do. You can simplify your code in this way.
function sum(arr) {
return arr.reduce((acc, item) => acc += item[1], 0);
}
const result = sum(MyArray.M[0].GA.L) + sum(MyArray.M[0].GA.M) + sum(MyArray.M[0].GA.R) + sum(MyArray.M[0].GA.RW);
This is a good example of a use for Array.prototype.reduce. The reduce method loops through all the elements of an array, and uses an accumulator to carry a result through the operation.
const someArray = [ /* any number of values */ ]
const sum = someArray.reduce( ( acc, val ) => ( acc + val )
You can take this a step further and write the callback as a function expression, and dump all of your arrays into a BIGGER array, and use reduce on THAT ONE too!
const summation = ( acc, val ) => ( acc + val )
const sumOfSums = ( acc, val ) => ( acc + val.reduce( summation, 0 ) )
const arrayOfArrays= [
MyArray.M[0].GA.L,
MyArray.M[0].GA.M,
MyArray.M[0].GA.R
MyArray.M[0].GA.RW
]
const total = arrayOfArrays.reduce( sumOfSums, 0 )
console.log( `output: ${total}` )

Reactjs: How to get values from array of objects

I am a beginner in rectjs. In my project, there is a list of objects stored in "groupedItems", and using sort() to order them and stored them into a variable "numAscending".
Now its structure is in the above picture. but I want to change them like in the below picture.
Here is the code which I tried.
groupedItems.map((items)=>{
numAscending = [...items].sort((a, b) => a.subsolution_name - b.subsolution_name);
temp.push({numAscending})
})
console.log("temp", temp)
// result = temp.map((option, key) => {
// console.log("eeeeeeee", option)
// option.map((item)=>{
// console.log("iteee", item)
// })
// });
// console.log('result', result);
I tried to fix it but failed (lines are started with //). Please give me a suggestion to solve this problem.
You probably could flatten the groupedItems array's element values, which appear to be arrays, and then sort the overall result array.
Example:
const result = groupedItems
.flat(Number.POSITIVE_INFINITY)
.sort((a, b) => a.subsolution_name - b.subsolution_name);
You can reduce it to get the array and then sort it
const reducedItems = groupedItems.reduce((prev,curr)=>{
return [...prev,...curr.numAscending]
},[]);
const sortedItems = reducedItems.sort((a, b) => a.subsolution_name - b.subsolution_name);

how to compare between two array that is inside one same array? [duplicate]

I have two arrays [a,b,c,d] and [b,d,f,h].
I want to get an array back with the common elements [b,d].
I can achieve that with a combination of filter and indexOf:
[a,b,c,d].filter(el => [b,d,f,h].indexOf(el) !== -1)
but I was wondering if and how I can do the same with reduce.
I admit that, despite looking at many examples, reduce still is to me one of the most obscure JS methods, so I'd really appreciate some advice.
ES6, a propoosal with Array#includes
The includes() method determines whether an array includes a certain element, returning true or false as appropriate.
On every loop of aa, reduce adds the element to the result array if the value is found in the test array bb. If not found, the former result is returned.
var aa = ['a','b','c','d'],
bb = ['b','d','f','h'],
cc = aa.reduce((r, a) => bb.includes(a) && r.concat(a) || r, []);
console.log(cc);
Just a smarter approach with using a single array which contains all arrays.
var aa = ['a','b','c','d'],
bb = ['b','d','f','h'],
result = [aa, bb].reduce((a, b) => a.filter(c => b.includes(c)));
console.log(result);
Reduce is designed to return a single value from a list of items. So filter makes much more sense here.
A good use for reduce would be to return the total number of common elements. Check it out here: https://jsfiddle.net/c69vgzL4/
var a = ['a','b','c','d']
var b = ['b','d','f','h']
var number_of_common = b.reduce(function(prev, next) {
return prev + (a.indexOf(next) + 1 ? 1 : 0)
}, 0)
$('body').html(number_of_common)
Not only two arrays but for an intersection of n arrays... Let's invent Array.prototype.intersect()
Array.prototype.intersect = function(...a) {
return [this,...a].reduce((p,c) => p.filter(e => c.includes(e)));
}
var arrs = [[0,2,4,6,8],[4,5,6,7],[4,6]],
arr = [0,1,2,3,4,5,6,7,8,9];
console.log(JSON.stringify(arr.intersect(...arrs)));
// or just do
console.log(JSON.stringify(["a","b","c","d"].intersect(["b","d","f","h"])));

foldr that doesn't crash and works reasonably well

I want a foldr that's similar to the foldr in Haskell or lisp. My foldr causes stack overflow on large arrays, and probably because large numbers of pending operations on the stack can't be reduced until it hits the base case. How would you optimize my foldr so it works reasonably well for large arrays.
const foldr = (f, acc, [x, ...xs]) =>
(typeof x === 'undefined')
? acc
: f (x, foldr (f, acc, xs))
foldr((x, acc) => x + acc, 0, [...Array(100000).keys()])
foldr is pretty nearly reduceRight:
const flip = f => (a, b) => f(b, a)
const foldr = (f, acc, arr) =>
arr.reduceRight(flip(f), acc)
Replace arr.reduceRight with [...arr].reduceRight if you’d like to keep the support for arbitrary iterables that [x, ...xs] unpacking gives you.
const flip = f => (a, b) => f(b, a)
const foldr = (f, acc, arr) =>
arr.reduceRight(flip(f), acc)
console.log(foldr((x, acc) => x + acc, 0, [...Array(100000).keys()]))
The problem is that the default list-like structure that JavaScript uses are mutable arrays (not true c-like arrays, they may internally be implemented as trees) while functional languages like Haskell or Lisp use linked lists. You can get the first element and the rest of linked list without mutation in constant time. If you want to do the same in JavaScript (without mutation), you have to create (allocate) new array to get the rest of the array.
However, the whole foldr can be implemented with internal mutation. The whole function won't do any external mutation:
const foldr = (f, initialValue, arr) => {
let value = initialValue;
for (let i = arr.length - 1; i >= 0; i--) {
value = f(arr[i], value)
}
return value;
}

Array intersection (set-theoretic) with Array.prototype.reduce

I have two arrays [a,b,c,d] and [b,d,f,h].
I want to get an array back with the common elements [b,d].
I can achieve that with a combination of filter and indexOf:
[a,b,c,d].filter(el => [b,d,f,h].indexOf(el) !== -1)
but I was wondering if and how I can do the same with reduce.
I admit that, despite looking at many examples, reduce still is to me one of the most obscure JS methods, so I'd really appreciate some advice.
ES6, a propoosal with Array#includes
The includes() method determines whether an array includes a certain element, returning true or false as appropriate.
On every loop of aa, reduce adds the element to the result array if the value is found in the test array bb. If not found, the former result is returned.
var aa = ['a','b','c','d'],
bb = ['b','d','f','h'],
cc = aa.reduce((r, a) => bb.includes(a) && r.concat(a) || r, []);
console.log(cc);
Just a smarter approach with using a single array which contains all arrays.
var aa = ['a','b','c','d'],
bb = ['b','d','f','h'],
result = [aa, bb].reduce((a, b) => a.filter(c => b.includes(c)));
console.log(result);
Reduce is designed to return a single value from a list of items. So filter makes much more sense here.
A good use for reduce would be to return the total number of common elements. Check it out here: https://jsfiddle.net/c69vgzL4/
var a = ['a','b','c','d']
var b = ['b','d','f','h']
var number_of_common = b.reduce(function(prev, next) {
return prev + (a.indexOf(next) + 1 ? 1 : 0)
}, 0)
$('body').html(number_of_common)
Not only two arrays but for an intersection of n arrays... Let's invent Array.prototype.intersect()
Array.prototype.intersect = function(...a) {
return [this,...a].reduce((p,c) => p.filter(e => c.includes(e)));
}
var arrs = [[0,2,4,6,8],[4,5,6,7],[4,6]],
arr = [0,1,2,3,4,5,6,7,8,9];
console.log(JSON.stringify(arr.intersect(...arrs)));
// or just do
console.log(JSON.stringify(["a","b","c","d"].intersect(["b","d","f","h"])));

Categories