I have a comma separated string in JavaScript that I want to separate into mutiple arrays, for each column but I want to ignore the first couple of lines. So for instance I want to convert the following string,
let data = "test,data,\n,ignore,this,\n,A,B,C,\n,1,2,3,\n,1,2,3";
into arrays like the following.
["A", "1", "1"]
["B", "2", "2"]
["C", "3", "3"]
EDIT
Ths is my initial solution that I tried. Like it works but it's not really a nice solution:/
for (let i = 1; i < out.length; i++)
{
let arr = out[i].split(',');
if (i === 1)
{
for (let j = 0; j < columns; j++)
{
let col = "arr" + j;
console.log(col);
obj[col] = [arr[j]];
}
console.log(obj);
}
else
{
for (let j = 0; j < columns; j++)
{
let col = "arr" + j;
let val = arr[j];
if (j !== "")
{
obj[col].push(val);
}
}
}
}
I should point out that I eventually want to create a map of the letters to corresponding array of numbers and I won't know what the key value will be. So I'll be trying to get something like the following,
"A": ["1", "1"]
"B": ["2", "2"]
"C": ["3", "3"]
You could split by ',\n,' for getting lines and for the items split by comma. Then omit the first two arrays.
var data = "test,data,\n,ignore,this,\n,A,B,C,\n,1,2,3,\n,1,2,3",
result = data.split(',\n,').map(s => s.split(',')).slice(2);
console.log(result);
for your expected result you first have to split a string by ',' and then run for loop on a resulted array and inside that convert, you alphabet with a number and compare numbers if match found than push it into a respective array.
like below code
var datArray= [];
a = [];
b = [];
c = [];
let data = "test,data,\n,ignore,this,\n,A,B,C,\n,1,2,3,\n,1,2,3";
datArray = data.split(',');
for(var i = 0; i < datArray.length; i++) {
if(datArray[i] == 'A' || datArray[i] == 1) {
a.push(datArray[i]);
} else if(datArray[i] == 'B' || datArray[i] == 2) {
b.push(datArray[i]);
} else if(datArray[i] == 'C' || datArray[i] == 3) {
c.push(datArray[i]);
}
}
console.log(a);
console.log(b);
console.log(c);
this is one of the way you can do...
This method is not hard coded ! With this method you can handle :
ABCDEF.... , 1 2 3 4 5 6 ...
We will split for first action. Then detect Not A Number function isNaN to detect A B C .
Array helpers :
var notNumber = [];
var numbers = [];
to store data .
On the end generate your results arrays !
Try this :
var data = "test,data,\n,ignore,this,\n,A,B,C,\n,1,2,3,\n,1,2,3";
var handler = data.split(",");
var preventFlag = true;
var countNaN = 0;
var notNumber = [];
var numbers = [];
//console.log(handler);
for (var x = 0;x < handler.length;x++) {
var currentData = handler[x];
if (preventFlag == false) {
if ( isNaN(currentData) ) {
notNumber.push(currentData);
}
else {
if (currentData != "\n") {
numbers.push(currentData);
}
}
}
if (currentData == "this"){
preventFlag = false;
}
}
//console.log(notNumber)
//console.log(numbers)
for (var z = 0; z < notNumber.length;z++) {
window["result" + z] = [];
window["result" + z].push(notNumber[z]);
//console.log(window["result0"])
window["result" + z].push(numbers[z])
window["result" + z].push(numbers[z + (notNumber.length) ])
}
// GENERATE RESULT ARRAY
console.log(window["result0"]);
console.log(window["result1"]);
console.log(window["result2"]);
//["A", "1", "1"]
//["B", "2", "2"]
//["C", "3", "3"]
Related
I have data like this.
var abc =",,,,,,,,,,,,,,,paul,2000,12sc21,logan,123,21sdf34,vfsarwe,456456,32fd23";
abc = abc.split(",");
let stub={};
var results=[];
var key=["name","value","acc"];
var i=0;
var j=0;
for( var i = 0 ; i <abc.length - 1;i++){
stub[key[j]=abc[i];
j++
if(j==3){
results.push(stub);
stub={};
j=0;
}
}
abc = results;
I would like to get those values arranges in form of array of object having those 3 keys:
output should be:
abc = [{"name": "paul", "value": "2000","acc":"12sc21"},{"name":"logan","value":"123","acc":"21sdf34"},{"name":"vfsarwe","value":"456456","acc":"32fd23"}];
but not able to get the desired output. this output only comes when string don't have ,,,,,, in starting. But the data i'm getting is sometimes having ,,,,, in stating.
You can use abc.replace(/(^[,\s]+)/g, '') to remove leading commas or whitespace from the String. Your for loop is also not running for long enough; it is looping until there is only one element left in the Array and then stopping.
Change
for(var i = 0 ; i < abc.length-1; i++)
To
for(var i = 0 ; i < abc.length; i++)
var abc =",,,,,,,,,,,,,,,paul,2000,12sc21,logan,123,21sdf34,vfsarwe,456456,32fd23";
abc = abc.replace(/(^[,\s]+)|([,\s]+$)/g, '').split(",");
let stub={};
var results=[];
var key=["name","value","acc"];
var i=0;
var j=0;
for(var i = 0 ; i < abc.length; i++){
stub[key[j]]=abc[i];
j++
if(j==3){
results.push(stub);
stub={};
j=0;
}
}
abc = results;
console.log(abc);
You can use .replace(/^\,+/, '') to remove all leading commas, then split by comma to get an array, then loop over this array using 3 as step and construct your results:
var abc = ",,,,,,,,,,,,,,,paul,2000,12sc21,logan,123,21sdf34,vfsarwe,456456,32fd23";
var arr = abc.replace(/^\,+/, '').split(",");
var results = [];
for (var i = 0; i < arr.length; i = i + 3) {
results.push({
"name": arr[i],
"value": arr[i + 1],
"acc": arr[i + 2]
});
}
Demo:
var abc = ",,,,,,,,,,,,,,,paul,2000,12sc21,logan,123,21sdf34,vfsarwe,456456,32fd23";
var arr = abc.replace(/^\,+/, '').split(",");
var results = [];
for (var i = 0; i < arr.length; i = i + 3) {
results.push({
"name": arr[i],
"value": arr[i + 1],
"acc": arr[i + 2]
});
}
console.log(results);
You are on the right track with splitting your data on ,. You can then split the data in to chunks of 3, and from there map each chunk to a dict.
var data = ",,,,,,,,,,,,,,,paul,2000,12sc21,logan,123,21sdf34,vfsarwe,456456,32fd23";
var split = data.split(",");
var chunked = [];
while (split.length) {
chunked.push(split.splice(0,3));
}
var res = chunked.map((i) => {
if (!i[0] || !i[1] || !i[2]) {
return null;
}
return {
name: i[0],
value: i[1],
acc: i[2]
};
}).filter((i) => i !== null);
console.log(res);
You can use:
abc.replace(/,+/g, ',').replace(/^,|,$/g, '').split(',');
The regEx replaces removes the data that you are not interested in before performing the split.
or
abc.split(',').filter(Boolean);
The filter(Boolean) will remove the items from the array that could be the equivalent of false once the array has been instantiated.
EDIT:
var abc =",,,,,,,,,,,,,,,paul,2,000,12sc21,logan,123,21sdf34,vfsarwe,456456,32fd23";
var array = abc.replace(/,+/g, ',').replace(/^,|,$/g, '').split(/,([0-9,]+),/);
array = array.filter(Boolean).reduce(function(acc, item) {
if (item.match(/^[0-9,]+$/)) {
acc.push(item);
} else {
acc = acc.concat(item.split(','));
}
return acc;
}, []);
This question already has answers here:
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
Closed 6 years ago.
I want to push values of 3 arrays in a new array without repeating the same values
var a = ["1", "2", "3"];
var b = ["3", "4", "5"];
var c = ["4", "5", "6"];
var d = [];
function newArray(x, y, z) {
for(var i = 0; i < d.length; i++) {
if(d.length == -1) {
d[i].push(a[i])
}
}
for(var i = 0; i < d.length; i++) {
if(d.length == -1) {
d[i].push(y[i])
}
}
for(var i = 0; i < d.length; i++) {
if(d.length == -1) {
d[i].push(z[i])
}
}
}
newArray(a, b, c);
d = ["1", "2", "3", "4", "5", "6"];
You can use concat() and Set together as below,
var a = ["1","2","3"];
var b = ["3","4","5"];
var c = ["4","5","6"];
var d = a.concat(b).concat(c);
var set = new Set(d);
d = Array.from(set);
console.log(d);
If your goal is to remove duplicates, you can use a set,
var arr = [1, 2, 3, 4, 5, 5, 6, 6, 6, 7]
var mySet = new Set(arr)
var filteredArray = Array.from(mySet)
console.log(filteredArray.sort()) // [1,2,3,4,5,6,7]
var a = ["1","2","3"]
, b = ["3","4","5"]
, c = ["4","5","6"]
, d = [];
function newArray(x,y,z) {
x.concat(y,z).forEach(item =>{
if (d.indexOf(item) == -1)
d.push(item);
});
return d;
}
console.log(newArray(a,b,c));
You could save yourself some time and effort with the very useful utility library Lodash.
The function you're looking for is Union
As stated by Lodash:
Creates an array of unique values, in order, from all given arrays
using SameValueZero for equality comparisons.
Example
_.union([2], [1, 2]);
// => [2, 1]
var a = ["1", "2", "3"];
var b = ["3", "4", "5"];
var c = ["4", "5", "6"];
var d = [];
var hash = [];
AddToHash(a);
AddToHash(b);
AddToHash(c);
function AddToHash(arr) {
for (var i = 0; i < arr.length; i++) {
if (!hash[arr[i]]) {
hash[arr[i]] = 1;
} else
hash[arr[i]] += 1;
}
}
for (var i = 0; i < hash.length; i++) {
d.push(i);
}
console.log(d);
Hope this helps
Here is another version:
var d = b.concat(c);
d.forEach(function(el) {
if (a.indexOf(el) === -1) {
a.push(el)
}
})
ES6 version:
let d = b.concat(c);
d.forEach(el => {
if (a.indexOf(el) === -1) {
a.push(el)
}
})
I have a string like this:
var str = 'My_Type_1=SSD&My_Value_1=16GB&My_Category_1=Disk Capacity&My_Type_2=Sony
&My_Value_2=PS4&My_Category_2=Console&My_rowOrder=2,1';
The string mostly has 3 parts except the last key:
Part 1 -> My - is a Common Prefix
Part 2 -> Type or Value or Category and it can keep changing
Part 3 -> It's a numeric value binding Part 1, Part 2 and Part 3 like Spreadsheet row.
The last key is always called
My_rowOrder and it's a comma delimeted value. It specifies how to construct the output array.
In the above example, 2,1 means a key value pair of
My_Type_2=Sony&My_Value_2=PS4&My_Category_2=Console should be the first in the output array.
Using JavaScript, I would like to parse the string and create an array out of it, such that the output is:
Array
(
[ 0 ] => Array
(
[Type] => Sony
[Value] => PS4
[Category] => Console
[Row] => 2
)
[ 1 ] => Array
(
[Type] => SSD
[Value] => 16GB
[Category] => Disk Capacity
[Row] => 1
)
)
How can I do this? I am partially able to do it this way:
function StringToArray(string) {
var request = {};
var pairs = string.split('&');
for (var i = 0; i < pairs.length-1; i++) {
var pair = pairs[i].split('=');
request[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
//I think I am in the right track, but need assistance
}
Your example output uses associative arrays, which JavaScript doesn't have, but you can use an array of objects instead.
This example outputs an array of objects, in the order specified by the rowOrder parameter. It trims the prefix (defined by prefix), and also trims the row number from the end of the key.
This will also work with the parameters in any order - e.g. you can mix them and it will parse as necessary, and the rowOrder parameter can appear anywhere in the string (doesn't have to be at the end).
Demo
function StringToArray(string) {
var prefix = 'My_'; // set the prefix
var output = [], request = [];
var pairs = string.split('&');
var order;
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
if (pair[0].replace(prefix, '') == 'rowOrder') {
order = pair[1];
} else {
var key = decodeURIComponent(pair[0]);
var pos = key.lastIndexOf('_');
var trimmedKey = key.substring(0, pos).replace(prefix, '');
var row = key.substring(pos + 1);
var value = decodeURIComponent(pair[1]);
var found = false;
for (var j = 0; j < output.length; j++) {
if (output[j].Row == row) {
output[j][trimmedKey] = value;
found = true;
}
}
if (!found) {
var obj = { 'Row': row };
obj[trimmedKey] = value;
output.push(obj);
}
}
}
// do the ordering based on the rowOrder parameter
var orderList = order.split(",");
for(var k=0; k<orderList.length; k++){
for(var l=0; l<output.length; l++){
if(output[l].Row == orderList[k]){
request.push(output[l]);
break;
}
}
}
return request;
}
Outputs an array of objects in the order specified by the My_rowOrder parameter:
[
{
Row: "2",
Type: "Sony",
Value: "PS4",
Category: "Console"
},
{
Row: "1",
Type: "SSD",
Value: "16GB",
Category: "Disk Capacity"
}
]
This may works for you...
<script>
var data = "My_Type_2=Sony&My_Value_2=PS4&My_Category_2=Console";
var array = new Array();
alert(JSON.stringify(URLToArray(data)));
function URLToArray(url) {
var request = {};
var pairs = url.substring(url.indexOf('?') + 1).split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
request[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
return request;
}
</script>
Try this:
function StringToArray(string) {
var request = [[],[]];
var pairs = string.split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
request[pair[0].slice(-1)-1][decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
//console.log(request)
}
I have two arrays like below
var arr = ["x", "y", "z", "a", "b", "c"];
var tgtArr = [{val:"a"}, {val:"b"}]; It does not need to be as lengthy as Array `arr`
This is what I have tried
var dest = new Array(arr.length);
for(var i = 0; i < arr.length; i++){
for(var k = 0; k < tgtArr.length; k++){
dest[i] = dest[i] || [];
if(tgtArr[k].val == arr[i]){
dest[i] = arr[i];
}
}
}
console.log(dest);
My Expected output is (for above tgtArr value)
[{}, {}, {}, {val:"a"}, {val:"b"}, {}];
if tgtArr is empty Array
[{},{},{},{},{},{}]
Here is the fiddle. Any alternative for this, it seems not a good way to me as I am iterating through the entire array everytime.
Short:
var result = arr.map(function(x) {
return tgtArr.some(function(o) { return o.val == x; }) ? {val:x} : {};
});
This is more efficient:
var set = {};
tgtArr.forEach(function(obj, i) {
set[obj.val] = true;
});
var result = arr.map(function(x) {
return x in set ? {val:x} : {};
});
This is the same as Paul's answer, but with a loop instead of map. It collects the keys first based on the val property, then creates a new array either with empty objects if the key isn't in tgtArr, or copies a reference to the object from tgtArr if it is:
function newArray(arr, tgtArr) {
var keys = {},
i = tgtArr.length,
j = arr.length,
newArr = [];
// Get keys
while (i--) keys[tgtArr[i].val] = tgtArr[i];
// Make new array
while (j--) newArr[j] = arr[j] in keys? keys[arr[j]] : {};
return newArr;
}
It should be efficient as it only traverses each array once.
var dest = new Array(arr.length);
for(var i = 0; i < arr.length; i++){
dest[i] = {}
for(var k = 0; k < tgtArr.length; k++){
if(tgtArr[k].val == arr[i]){
dest[i] = tgtArr[k];
}
}
}
console.log(dest);
I like using map rather than loops for this kind of thing (Fiddle):
var result = arr.map(function(x) {
var match = tgtArr.filter(function(y) {
return y.val == x;
});
if (match.length == 1) return match[0];
else return {};
});
This is a possibly inefficient, in that it traverses tgtArr for every item in arr, so O(n*m). If needed, you could fix that by pre-processing tgtArr and converting it to a hash map (Fiddle). This way you've got an O(n+m) algorithm (traverse each array once):
var tgtMap = {};
tgtArr.forEach(function(x) { tgtMap[x.val] = x; })
var result = arr.map(function(x) {
var match = tgtMap[x];
return match || {};
});
var tmp = {};
for (var i = 0; i < tgtArr.length; i++) {
tmp[tgtArr[i].val] = i;
}
var dest = [];
for (var i = 0; i < arr.length; i++) {
var obj= tmp[arr[i]] === undefined ? {} : tgtArr[tmp[arr[i]]];
dest.push(obj);
}
DEMO
This question already has answers here:
Cartesian product of multiple arrays in JavaScript
(35 answers)
Closed 1 year ago.
I'm having trouble coming up with code to generate combinations from n number of arrays with m number of elements in them, in JavaScript. I've seen similar questions about this for other languages, but the answers incorporate syntactic or library magic that I'm unsure how to translate.
Consider this data:
[[0,1], [0,1,2,3], [0,1,2]]
3 arrays, with a different number of elements in them. What I want to do is get all combinations by combining an item from each array.
For example:
0,0,0 // item 0 from array 0, item 0 from array 1, item 0 from array 2
0,0,1
0,0,2
0,1,0
0,1,1
0,1,2
0,2,0
0,2,1
0,2,2
And so on.
If the number of arrays were fixed, it would be easy to make a hard coded implementation. But the number of arrays may vary:
[[0,1], [0,1]]
[[0,1,3,4], [0,1], [0], [0,1]]
Any help would be much appreciated.
Here is a quite simple and short one using a recursive helper function:
function cartesian(...args) {
var r = [], max = args.length-1;
function helper(arr, i) {
for (var j=0, l=args[i].length; j<l; j++) {
var a = arr.slice(0); // clone arr
a.push(args[i][j]);
if (i==max)
r.push(a);
else
helper(a, i+1);
}
}
helper([], 0);
return r;
}
Usage:
cartesian([0,1], [0,1,2,3], [0,1,2]);
To make the function take an array of arrays, just change the signature to function cartesian(args) instead of using rest parameter syntax.
I suggest a simple recursive generator function:
// JS
function* cartesianIterator(head, ...tail) {
const remainder = tail.length ? cartesianIterator(...tail) : [[]];
for (let r of remainder) for (let h of head) yield [h, ...r];
}
// get values:
const cartesian = items => [...cartesianIterator(items)];
console.log(cartesian(input));
// TS
function* cartesianIterator<T>(items: T[][]): Generator<T[]> {
const remainder = items.length > 1 ? cartesianIterator(items.slice(1)) : [[]];
for (let r of remainder) for (let h of items.at(0)!) yield [h, ...r];
}
// get values:
const cartesian = <T>(items: T[][]) => [...cartesianIterator(items)];
console.log(cartesian(input));
You could take an iterative approach by building sub arrays.
var parts = [[0, 1], [0, 1, 2, 3], [0, 1, 2]],
result = parts.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));
console.log(result.map(a => a.join(', ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
After doing a little research I discovered a previous related question:
Finding All Combinations of JavaScript array values
I've adapted some of the code from there so that it returns an array of arrays containing all of the permutations:
function(arraysToCombine) {
var divisors = [];
for (var i = arraysToCombine.length - 1; i >= 0; i--) {
divisors[i] = divisors[i + 1] ? divisors[i + 1] * arraysToCombine[i + 1].length : 1;
}
function getPermutation(n, arraysToCombine) {
var result = [],
curArray;
for (var i = 0; i < arraysToCombine.length; i++) {
curArray = arraysToCombine[i];
result.push(curArray[Math.floor(n / divisors[i]) % curArray.length]);
}
return result;
}
var numPerms = arraysToCombine[0].length;
for(var i = 1; i < arraysToCombine.length; i++) {
numPerms *= arraysToCombine[i].length;
}
var combinations = [];
for(var i = 0; i < numPerms; i++) {
combinations.push(getPermutation(i, arraysToCombine));
}
return combinations;
}
I've put a working copy at http://jsfiddle.net/7EakX/ that takes the array you gave earlier ([[0,1], [0,1,2,3], [0,1,2]]) and outputs the result to the browser console.
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
console.log(charSet.reduce((a,b)=>a.flatMap(x=>b.map(y=>x+y)),['']))
Just for fun, here's a more functional variant of the solution in my first answer:
function cartesian() {
var r = [], args = Array.from(arguments);
args.reduceRight(function(cont, factor, i) {
return function(arr) {
for (var j=0, l=factor.length; j<l; j++) {
var a = arr.slice(); // clone arr
a[i] = factor[j];
cont(a);
}
};
}, Array.prototype.push.bind(r))(new Array(args.length));
return r;
}
Alternative, for full speed we can dynamically compile our own loops:
function cartesian() {
return (cartesian.cache[arguments.length] || cartesian.compile(arguments.length)).apply(null, arguments);
}
cartesian.cache = [];
cartesian.compile = function compile(n) {
var args = [],
indent = "",
up = "",
down = "";
for (var i=0; i<n; i++) {
var arr = "$"+String.fromCharCode(97+i),
ind = String.fromCharCode(105+i);
args.push(arr);
up += indent+"for (var "+ind+"=0, l"+arr+"="+arr+".length; "+ind+"<l"+arr+"; "+ind+"++) {\n";
down = indent+"}\n"+down;
indent += " ";
up += indent+"arr["+i+"] = "+arr+"["+ind+"];\n";
}
var body = "var res=[],\n arr=[];\n"+up+indent+"res.push(arr.slice());\n"+down+"return res;";
return cartesian.cache[n] = new Function(args, body);
}
var f = function(arr){
if(typeof arr !== 'object'){
return false;
}
arr = arr.filter(function(elem){ return (elem !== null); }); // remove empty elements - make sure length is correct
var len = arr.length;
var nextPerm = function(){ // increase the counter(s)
var i = 0;
while(i < len)
{
arr[i].counter++;
if(arr[i].counter >= arr[i].length){
arr[i].counter = 0;
i++;
}else{
return false;
}
}
return true;
};
var getPerm = function(){ // get the current permutation
var perm_arr = [];
for(var i = 0; i < len; i++)
{
perm_arr.push(arr[i][arr[i].counter]);
}
return perm_arr;
};
var new_arr = [];
for(var i = 0; i < len; i++) // set up a counter property inside the arrays
{
arr[i].counter = 0;
}
while(true)
{
new_arr.push(getPerm()); // add current permutation to the new array
if(nextPerm() === true){ // get next permutation, if returns true, we got them all
break;
}
}
return new_arr;
};
Here's another way of doing it. I treat the indices of all of the arrays like a number whose digits are all different bases (like time and dates), using the length of the array as the radix.
So, using your first set of data, the first digit is base 2, the second is base 4, and the third is base 3. The counter starts 000, then goes 001, 002, then 010. The digits correspond to indices in the arrays, and since order is preserved, this is no problem.
I have a fiddle with it working here: http://jsfiddle.net/Rykus0/DS9Ea/1/
and here is the code:
// Arbitrary base x number class
var BaseX = function(initRadix){
this.radix = initRadix ? initRadix : 1;
this.value = 0;
this.increment = function(){
return( (this.value = (this.value + 1) % this.radix) === 0);
}
}
function combinations(input){
var output = [], // Array containing the resulting combinations
counters = [], // Array of counters corresponding to our input arrays
remainder = false, // Did adding one cause the previous digit to rollover?
temp; // Holds one combination to be pushed into the output array
// Initialize the counters
for( var i = input.length-1; i >= 0; i-- ){
counters.unshift(new BaseX(input[i].length));
}
// Get all possible combinations
// Loop through until the first counter rolls over
while( !remainder ){
temp = []; // Reset the temporary value collection array
remainder = true; // Always increment the last array counter
// Process each of the arrays
for( i = input.length-1; i >= 0; i-- ){
temp.unshift(input[i][counters[i].value]); // Add this array's value to the result
// If the counter to the right rolled over, increment this one.
if( remainder ){
remainder = counters[i].increment();
}
}
output.push(temp); // Collect the results.
}
return output;
}
// Input is an array of arrays
console.log(combinations([[0,1], [0,1,2,3], [0,1,2]]));
You can use a recursive function to get all combinations
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
let loopOver = (arr, str = '', final = []) => {
if (arr.length > 1) {
arr[0].forEach(v => loopOver(arr.slice(1), str + v, final))
} else {
arr[0].forEach(v => final.push(str + v))
}
return final
}
console.log(loopOver(charSet))
This code can still be shorten using ternary but i prefer the first version for readability 😊
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
let loopOver = (arr, str = '') => arr[0].map(v => arr.length > 1 ? loopOver(arr.slice(1), str + v) : str + v).flat()
console.log(loopOver(charSet))
Another implementation with ES6 recursive style
Array.prototype.cartesian = function(a,...as){
return a ? this.reduce((p,c) => (p.push(...a.cartesian(...as).map(e => as.length ? [c,...e] : [c,e])),p),[])
: this;
};
console.log(JSON.stringify([0,1].cartesian([0,1,2,3], [[0],[1],[2]])));