How can I create any combination for the contents of two arrays?

I have two arrays:

var array1=["A","B","C"]; var array2=["1","2","3"]; 

How can I set another array to contain all the combinations above, so that:

 var combos=["A1","A2","A3","B1","B2","B3","C1","C2","C3"]; 
+11
source share
8 answers

Loop this shape

 combos = [] //or combos = new Array(2); for(var i = 0; i < array1.length; i++) { for(var j = 0; j < array2.length; j++) { //you would access the element of the array as array1[i] and array2[j] //create and array with as many elements as the number of arrays you are to combine //add them in //you could have as many dimensions as you need combos.push(array1[i] + array2[j]) } } 
+6
source

Or, if you want to create combinations with an arbitrary number of arrays of arbitrary sizes ... (I'm sure you can do this recursively, but since this is not an interview, I use an iterative "odometer" instead for this ... it increases " number "with each digit" digit "base-n" based on the length of each array) ... for example ...

 combineArrays([ ["A","B","C"], ["+", "-", "*", "/"], ["1","2"] ] ) 

... is returning ...

 [ "A+1","A+2","A-1", "A-2", "A*1", "A*2", "A/1", "A/2", "B+1","B+2","B-1", "B-2", "B*1", "B*2", "B/1", "B/2", "C+1","C+2","C-1", "C-2", "C*1", "C*2", "C/1", "C/2" ] 

... each of which corresponds to an odometer value that selects an index from each array ...

 [0,0,0], [0,0,1], [0,1,0], [0,1,1] [0,2,0], [0,2,1], [0,3,0], [0,3,1] [1,0,0], [1,0,1], [1,1,0], [1,1,1] [1,2,0], [1,2,1], [1,3,0], [1,3,1] [2,0,0], [2,0,1], [2,1,0], [2,1,1] [2,2,0], [2,2,1], [2,3,0], [2,3,1] 

The odometer method allows you to easily generate the desired type of output, not just concatenated strings, as we have here. In addition, by avoiding recursion, we are avoiding the possibility - do I dare say this? - stack overflow ...

 function combineArrays( array_of_arrays ){ // First, handle some degenerate cases... if( ! array_of_arrays ){ // Or maybe we should toss an exception...? return []; } if( ! Array.isArray( array_of_arrays ) ){ // Or maybe we should toss an exception...? return []; } if( array_of_arrays.length == 0 ){ return []; } for( let i = 0 ; i < array_of_arrays.length; i++ ){ if( ! Array.isArray(array_of_arrays[i]) || array_of_arrays[i].length == 0 ){ // If any of the arrays in array_of_arrays are not arrays or zero-length, return an empty array... return []; } } // Done with degenerate cases... // Start "odometer" with a 0 for each array in array_of_arrays. let odometer = new Array( array_of_arrays.length ); odometer.fill( 0 ); let output = []; let newCombination = formCombination( odometer, array_of_arrays ); output.push( newCombination ); while ( odometer_increment( odometer, array_of_arrays ) ){ newCombination = formCombination( odometer, array_of_arrays ); output.push( newCombination ); } return output; }/* combineArrays() */ // Translate "odometer" to combinations from array_of_arrays function formCombination( odometer, array_of_arrays ){ // In Imperative Programmingese (ie, English): // let s_output = ""; // for( let i=0; i < odometer.length; i++ ){ // s_output += "" + array_of_arrays[i][odometer[i]]; // } // return s_output; // In Functional Programmingese (Henny Youngman one-liner): return odometer.reduce( function(accumulator, odometer_value, odometer_index){ return "" + accumulator + array_of_arrays[odometer_index][odometer_value]; }, "" ); }/* formCombination() */ function odometer_increment( odometer, array_of_arrays ){ // Basically, work you way from the rightmost digit of the "odometer"... // if you're able to increment without cycling that digit back to zero, // you're all done, otherwise, cycle that digit to zero and go one digit to the // left, and begin again until you're able to increment a digit // without cycling it...simple, huh...? for( let i_odometer_digit = odometer.length-1; i_odometer_digit >=0; i_odometer_digit-- ){ let maxee = array_of_arrays[i_odometer_digit].length - 1; if( odometer[i_odometer_digit] + 1 <= maxee ){ // increment, and you're done... odometer[i_odometer_digit]++; return true; } else{ if( i_odometer_digit - 1 < 0 ){ // No more digits left to increment, end of the line... return false; } else{ // Can't increment this digit, cycle it to zero and continue // the loop to go over to the next digit... odometer[i_odometer_digit]=0; continue; } } }/* for( let odometer_digit = odometer.length-1; odometer_digit >=0; odometer_digit-- ) */ }/* odometer_increment() */ 
+10
source

Assuming you are using a recent web browser with Array.forEach support:

 var combos = []; array1.forEach(function(a1){ array2.forEach(function(a2){ combos.push(a1 + a2); }); }); 

If you don't have forEach , this is a simple exercise to rewrite it without it. As previously proven, there are some performance benefits without using ... (Although I say that not so long ago, regular temporary JavaScript environments will optimize any current benefits for this otherwise.)

+7
source

Here is the functional programming of the ES6 solution:

 var array1=["A","B","C"]; var array2=["1","2","3"]; var result = array1.reduce( (a, v) => [...a, ...array2.map(x=>v+x)], []); /*---------OR--------------*/ var result1 = array1.reduce( (a, v, i) => a.concat(array2.map( w => v + w )), []); /*-------------OR(without arrow function)---------------*/ var result2 = array1.reduce(function(a, v, i) { a = a.concat(array2.map(function(w){ return v + w })); return a; },[] ); console.log(result); console.log(result1); console.log(result2) 
+3
source

Just in case, if someone is looking for a solution to Array.map

 var array1=["A","B","C"]; var array2=["1","2","3","4"]; console.log(array1.flatMap(d => array2.map(v => d + v))) 
+3
source

Make a loop like this ->

 let numbers = [1,2,3,4,5]; let letters = ["A","B","C","D","E"]; let combos = []; for(let i = 0; i < numbers.length; i++) { combos.push(letters[i] + numbers[i]); }; 

But you have to make an array of "numbers" and "letters" of the same length!

0
source

I had a similar requirement, but I needed to get all the key combinations of the object so that I could split it into several objects. For example, I needed to convert the following;

 { key1: [value1, value2], key2: [value3, value4] } 

to the next 4 objects

 { key1: value1, key2: value3 } { key1: value1, key2: value4 } { key1: value2, key2: value3 } { key1: value2, key2: value4 } 

I solved this with the splitToMultipleKeys login splitToMultipleKeys and the splitToMultipleKeys recursive function;

 function spreadKeys(master, objects) { const masterKeys = Object.keys(master); const nextKey = masterKeys.pop(); const nextValue = master[nextKey]; const newObjects = []; for (const value of nextValue) { for (const ob of objects) { const newObject = Object.assign({ [nextKey]: value }, ob); newObjects.push(newObject); } } if (masterKeys.length === 0) { return newObjects; } const masterClone = Object.assign({}, master); delete masterClone[nextKey]; return spreadKeys(masterClone, newObjects); } export function splitToMultipleKeys(key) { const objects = [{}]; return spreadKeys(key, objects); } 
0
source

Seeing a lot of for loops in all the answers ...

Here is a recursive solution that I came up with that will find all combinations of N numbers of arrays by taking 1 element from each array:

 const array1=["A","B","C"] const array2=["1","2","3"] const array3=["red","blue","green"] const combine = ([head, ...[headTail, ...tailTail]]) => { if (!headTail) return head const combined = headTail.reduce((acc, x) => { return acc.concat(head.map(h => '${h}${x}')) }, []) return combine([combined, ...tailTail]) } console.log('With your example arrays:', combine([array1, array2])) console.log('With N arrays:', combine([array1, array2, array3])) 
0
source

Source: https://habr.com/ru/post/906449/


All Articles