0

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

5
  • all you have to do is const newArr = [ array1,array2,array3 ] Commented Sep 16, 2020 at 5:36
  • no special logic required. Commented Sep 16, 2020 at 5:37
  • @Sujit.Warrier You are oversimplifying it because each of the input arrays represents a column, not a row Commented Sep 16, 2020 at 5:38
  • aah i understand. you need it to be a table like structure Commented Sep 16, 2020 at 5:41
  • and you need the values assigned right to left Commented Sep 16, 2020 at 5:42

5 Answers 5

2

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

Sign up to request clarification or add additional context in comments.

4 Comments

I have to admit, this is pretty slick and "Woah". Thanks.
😛 this is impressive
@Sheelpriy I realized that after and added a length object fix
👍 Now again impressive!
0

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);

Comments

0
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.

1 Comment

I made same mistake at first for numberToIterate. If none of sub array lengths are greater than 2 it fails, Add 3 as argument in Math.max also
0
  • 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)));

Comments

0

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)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.