Home > Enterprise >  Joining array columns based on headers
Joining array columns based on headers

Time:12-17

I need to combine the array results in js based on the header names. The number of arrays passed for processing is not known and it can vary from 2 to 30 plus arrays and the final expected result is a combination of column data based on header names.

The input array column orders may be shuffled as shown below

array1 = [
["A","B","C"], // headers
["AA1","BB1","CC1"],
["AAA1","BBB1","CCC1"], ...
]

array2 = [
["B","C","A", "D"], //headers
["BB2","CC2","AA2", "DD2"],
["BBB2","CCC2","AAA2","DDD2"],...
]

...

arrayn = [
["A","C","B", ...], //headers
["AAn","CCn","BBn", ...],
["AAAn","CCC2","BBBn", ...],...
]

result = 

[
["A","B","C", "D"],
["AA1","BB1","CC1",""],
["AAA1","BBB1","CCC1",""],
["AA2","BB2","CC2","DD2"],
["AAA2","BBB2","CCC2,"DDD2"],
...
["AAn","BBn","CCn",...],
["AAAn","BBBn","CCCn,...],
]

I have tried with

for(var i=0;i<array1;i  )
{
    for(var j=0;j<array2;j  )
    {
            if(array1[i][j]==array2[0][j])
            {
                result.push(array[i][j])
            
            }
    }
}

UDPATE: The number of columns may vary from input array, but they all would appear in the result. Like array2 has D column and the result would have DD2 and DDD2

CodePudding user response:

You have to loop through the arrays seperately. Keep a reference header, In each array mark the first element as the header and rest as data using spread operator. Loop through the rest of data by tracking the indices in the header for each array.

Working Code

const array1 = [
    ["A", "B", "C"], // headers
    ["AA1", "BB1", "CC1"],
    ["AAA1", "BBB1", "CCC1"],
]

const array2 = [
    ["B", "C", "A"], //headers
    ["BB2", "CC2", "AA2"],
    ["BBB2", "CCC2", "AAA2"],
]



const arrayn = [
    ["A", "C", "B"], //headers
    ["AAn", "CCn", "BBn"],
    ["AAAn", "CCC2", "BBBn"],
]

const result = [];
const header = ["A", "B", "C"];
result.push(header);

function addArray(arr) {
    const [itemHeader, ...rest] = arr;
    const [orderA, orderB, orderC] = [itemHeader.indexOf(header[0]), itemHeader.indexOf(header[1]), itemHeader.indexOf(header[2])];
    rest.forEach((item) => {
        const orderedArray = [item[orderA], item[orderB], item[orderC]];
        result.push(orderedArray);
    })
}

addArray(array1);
addArray(array2);
addArray(arrayn);
console.log(result);

EDIT

Generic Method

Logic

  • Use a function generateResult which accepys dynamic number of parameters.
  • Segregare the headers from that list. For that loop through the params. Take the first node of each param which is the header. flatMap it to generate the complete list of headers as a single array. Create a new set with this list to get the unique values, Sort it to define an order.
  • Loop through the params, split each params into two using spread operator. The first item is the header of that node which is called as nodeHeader and rest is the data.
  • The order of the output is obtained by comparing this node header and the main header list.
  • Loop through the data array and return the values in the specified order.

Working Fiddle

const array1 = [
    ["A", "B", "C"], // headers
    ["AA1", "BB1", "CC1"],
    ["AAA1", "BBB1", "CCC1"],
]

const array2 = [
    ["B", "C", "A", "D"], //headers
    ["BB2", "CC2", "AA2", "DD2"],
    ["BBB2", "CCC2", "AAA2", "DDD2"],
]


const array3 = [
    ["B", "C", "D"], //headers
    ["BB3", "CC3", "DD3"],
    ["BBB3", "CCC3", "DDD3"],
]

const arrayn = [
    ["A", "C", "B"], //headers
    ["AAn", "CCn", "BBn"],
    ["AAAn", "CCC2", "BBBn"],
]

const result = [];

function getNode(item, header) {
    const [ nodeHeader, ...data ] = item;
    const orderList = header.map(node => nodeHeader.indexOf(node));
    const retVal = data.map(node => orderList.map(order => order === -1 ? "" : node[order]));
    return retVal;
}

function generateResult(...list) {
    // Generate unique array of headers using set.
    const header = Array.from(new Set(list.flatMap(item => item[0]))).sort(); // Selecting header
    const rest = list.flatMap((item, index) => getNode(item, header));
    const result = [header, ...rest];
    console.log(result);
}

generateResult(array1, array2, array3, arrayn);

CodePudding user response:

What you do is just create a map with witch you can migrate old column to the new one. To to do so you have just to take the first array as reference and create a function that do the migration.

var array1 = [
["A","B","C"], // headers
["AA1","BB1","CC1"],
["AAA1","BBB1","CCC1"]];

var array2 = [
["B","C","A"], //headers
["BB2","CC2","AA2"],
["BBB2","CCC2","AAA2"]
];

// get the headers for result
// we take the first array as base then we add the other arary to it
var result = [];
result = array1;
var resultheader = result[0];
var resultheaderIndexMap = {};

//we create a map which indicate which letters belong te which column
for(var i = 0; i < resultheader.length; i  ){
    var tmpval = resultheader[i];
    resultheaderIndexMap[tmpval] = i;
}



function AppendArray(result, newArray, resultheaderIndexMap){



// We create a map from the header in order to migrate the old index 
// to the new one in order
var indexFromOldToNewMap = {};
var tpmHeeader = array2[0];

for(var i = 0; i< tpmHeeader.length; i   ){
    var tmpval = tpmHeeader[i];
    var newIndex = resultheaderIndexMap[tmpval];
    var oldIndex = i;
    indexFromOldToNewMap[oldIndex] = newIndex;
}

//then we use it to migrate 
for(var i = 1; i < array2.length; i  ){
    var tab = array2[i];
    var resultTab = [];
    for(var y = 0; y < tab.length; y  ){
        var newIndex = indexFromOldToNewMap[y];
        var tmpval = tab[y];
        resultTab[newIndex] = tmpval;        
    }
    result.push(resultTab);
}

return result;

}


AppendArray(result, array2, resultheaderIndexMap);
  • Related