Reputation: 109
I am getting 3 arrays from an api response obj. They can sometimes be empty or variable lengths.
Lets say I have these 3 arrays:
[]
["2a", "2b"]
["3a", "3b", "3c"]
I'd like to have the end result of combining these be a new array that contains 1 array per index:
[
["", "2a", "3a"],
["", "2b", "3b"],
["", "", "3c"]
]
Looking to see if someone has an "elegant" way to do this, as I can come up with a way to do this but it's rather grotesque.
Thanks
Upvotes: 0
Views: 381
Reputation: 171669
Put the three responses into another array then use a nested Array.from()
taking advantage of it's built in mapping function
const ar = [
[],
["2a", "2b"],
["3a", "3b", "3c"]
];
// get longest of either subarray or main array lengths
const len = {length: Math.max(...[...ar.map(e => e.length), ar.length])};
const res =
Array.from(len, (_,i) => Array.from(len, (_,j) => (ar[j] && ar[j][i]) || ''))
console.log(JSON.stringify(res))
Upvotes: 2
Reputation: 1745
I think this is what you are looking for. independent of the number of arrays and of any length.
function createMatrix(...arrays){
const numOfArrays = arrays.length; // rows
const longestArray = Math.max.apply({},arrays.map(a => a.length)) //columns
let matrix = []
for(let i =0; i<numOfArrays; i++){
matrix[i] = matrix[i] ||[];
for(let j=0; j<numOfArrays; j++){
matrix[i].push(arrays[j] && arrays[j][i] || '')
}
}
return matrix || [];
}
const result = createMatrix([1], [2, 22], [3, 33, 333])
const result2 = createMatrix([], [2, 22], [3, 33, 333], [4, 44, 444, 4444])
console.log(result)
console.log(result2)
Upvotes: 0
Reputation: 202856
O(m*n)
complexity where m is the number of arrays and n the length of arraysCode
const combineData = (...datas) => {
let dataProcessed = false;
let index = 0;
const combinedData = [];
while(!dataProcessed) {
combinedData.push([]); // push new array for index
dataProcessed = true; // assume data processed
datas.forEach(data => {
combinedData[index].push(data[index] ?? ""); // push value or ""
if (data[index + 1]) dataProcessed = false; // check next index
});
index++; // bump index
}
return combinedData;
};
const data1 = [];
const data2 = ["2a", "2b"];
const data3 = ["3a", "3b", "3c"];
const data4 = ["4a", "4b", "4c", "4d"];
const combineData = (...datas) => {
let dataProcessed = false;
let index = 0;
const combinedData = [];
while(!dataProcessed) {
combinedData.push([]);
dataProcessed = true;
datas.forEach(data => {
combinedData[index].push(data[index] ?? "");
if (data[index + 1]) dataProcessed = false;
});
index++;
}
return combinedData;
};
console.log(JSON.stringify(combineData(data1, data2, data3)));
console.log(JSON.stringify(combineData(data4, data1, data2, data3)));
Upvotes: 0
Reputation: 159
var arr1 = [];
var arr2 = ["2a", "2b"];
var arr3 = ["3a", "3b", "3c"];
var numberToIterate = Math.max(arr1.length, arr2.length, arr3.length);
var finalArr = [];
for(var i=0; i<numberToIterate; i++) {
var temp = [];
if(!arr1[i]){
arr1[i] = "";
}
if(!arr2[i]){
arr2[i] = "";
}
if(!arr3[i]){
arr3[i] = "";
}
temp.push(arr1[i]);
temp.push(arr2[i]);
temp.push(arr3[i]);
finalArr[i] = temp;
}
Your result will be saved in finalArr.
Upvotes: 0
Reputation: 29015
It seems you want to take a 2D array and "rotate" it so the rows become columns. They are all then padded at the front to match the longest columns. This can be achieved in three steps:
//helper functions
function findLongest(arr) {
return arr.reduce(
(longest, currentArray) => Math.max(longest, currentArray.length),
0
)
}
function padStart(targetLength, fillWith, array) {
const elementsNeeded = targetLength - array.length;
const start = Array(elementsNeeded).fill(fillWith);
return start.concat(array);
}
//from Fawad Ghafoor https://stackoverflow.com/a/17428705/
function transpose(array) {
return array[0].map((_, colIndex) => array.map(row => row[colIndex]));
}
//////
//using the helper functions
const startArr = [
[],
["2a", "2b"],
["3a", "3b", "3c"],
]
const longest = findLongest(startArr);
const paddedArray = startArr.map(arr => padStart(longest, "", arr));
const rotatedArray = transpose(paddedArray);
//format for betted display in the console:
const formattedArray = rotatedArray.map(arr => JSON.stringify(arr).replace(/"/g, "'"));
console.log(formattedArray);
Upvotes: 0