Blake
Blake

Reputation: 109

Take 3 variable length arrays and combine them into a arrays per index

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

Answers (5)

charlietfl
charlietfl

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

Sheelpriy
Sheelpriy

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

Drew Reese
Drew Reese

Reputation: 202856

  • Args array of arrays to process
  • Loop over arrays an index at a time and push into result arrays
  • If any data exists in the next index keep processing.
  • Return combined arrays
  • O(m*n) complexity where m is the number of arrays and n the length of arrays

Code

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

Preeti A.
Preeti A.

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

VLAZ
VLAZ

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:

  1. Find the longest array. This is the target length.
  2. Pad the start of each array with empty strings until it reaches the target length.
  3. Perform matrix transposition to "rotate" the array 90 degrees.

//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

Related Questions