JSG
JSG

Reputation: 1583

Merging nested array in JavaScript with id

I am a JavaScript beginner. I want to merge a nested array with "id" <-- unique for all the array of objects. The A and B keys are dynamic (ex. A, B, C, D, and so on) and can be added later. Whereas the dummy key is of a kind where if the dummy value of all the 3 arrays matches then only it will show in the final result; else it will show as - (hyphen)


let arr1 = [
  {
    A: 0.71,
    B: 0.52,
    id: 1,
    dummy: 1,
  },
  {
    A: 0.72,
    B: 0.50,
    id: 2,
    dummy: 1,
  },
];

let arr2 = [
  {
    A: 0.157,
    B: 0.02255,
    id: 1,
    dummy: 1,
  },
  {
    A: 0.16761,
    B: 0.028281,
    id: 2,
    dummy: 1,
  },
];

let arr3 = [
  {
    A: 0.55,
    B: 0.50,
    id: 1,
    dummy: 1,
  },
  {
    A: 0.5,
    B: 0.43,
    id: 2,
    dummy: 1,
  },
];

I want these in one array as finalArray with contains id and all the three arrays inside those with their respective ids

let finalArr = [
  {
    id: 1,
    dummy: 1,
    arr1_A: 0.71,
    arr1_B: 0.52,
    arr2_A: 0.157,
    arr2_B: 0.02255,
    arr3_A: 0.55,
    arr3_B: 0.5,
  },
  {
    id: 2,
    dummy: 1,
    arr1_A: 0.72,
    arr1_B: 0.5,
    arr2_A: 0.16761,
    arr2_B: 0.028281,
    arr3_A: 0.5,
    arr3_B: 0.43,
  },
];

Upvotes: 0

Views: 119

Answers (3)

Peter Thoeny
Peter Thoeny

Reputation: 7616

You can first gather the data by id using a .reduce(), then transform the data into your desired array format:

UPDATE 2022-12-09: C\I changed below code based on changed requirements by OP:

  • "I need to validate if dummy is same then we will print dummy else - (hypen)"
  • OP also changed the desired output from "arr1": { "A": 0.71, "B": 0.52 }, to a flat "arr1_A": 0.71, "arr1_B": 0.52,

let arr1 = [
  { A: 0.71, B: 0.52, id: 1, dummy: 1, },
  { A: 0.72, B: 0.50, id: 2, dummy: 1, },
];
let arr2 = [
  { A: 0.157,   B: 0.02255,  id: 1, dummy: 1, },
  { A: 0.16761, B: 0.028281, id: 2, dummy: 1, },
];
let arr3 = [
  { A: 0.55, B: 0.50, id: 1, dummy: 1, },
  { A: 0.5,  B: 0.43, id: 2, dummy: 99, },
];

let idMap = arr1.concat(arr2).concat(arr3).reduce((acc, obj) => {
  if(!acc[obj.id]) {
    acc[obj.id] = {
      dummy: obj.dummy,
      arrs: []
    }
  }
  if(obj.dummy != acc[obj.id].dummy) {
    acc[obj.id].dummy = '-';
  }
  acc[obj.id].arrs.push({ A: obj.A, B: obj.B });
  return acc;
}, {});
let finalArr = Object.keys(idMap).map(id => {
  let obj = {
    id: id,
    dummy: idMap[id].dummy
  };
  let idx = 1;
  idMap[id].arrs.forEach(o => {
    Object.keys(o).map(p => {
      obj['arr' + idx + '_' + p] = o[p];
    });
    idx++;
  });
  return obj;
});
console.log(finalArr);

Upvotes: 2

Terry Lennox
Terry Lennox

Reputation: 30675

You can use Array.reduce() to group the items by id.

First we'd gather up each array into an inputs object, combining the name and value of each array.

We can use Object.entries() along with .reduce() to iterate over our inputs.

A mapping object will be created with one entry for each id and a dummy value corresponding to the initial value for that id. If the dummy value for an id changes, we flag it with '-'.

We add a property to each value at id with the naming convention ${arr}_${prop} for each property in each iterated object.

We can finally use Object.values() to get the result as an array rather than an object.

const arr1 = [ { A: 0.71, B: 0.52, id: 1, dummy: 1, }, { A: 0.72, B: 0.50, id: 2, dummy: 1, }, ];
const arr2 = [ { A: 0.157, B: 0.02255, id: 1, dummy: 1, }, { A: 0.16761, B: 0.028281, id: 2, dummy: 1, }, ];
const arr3 = [ { A: 0.55, B: 0.50, id: 1, dummy: 1, }, { A: 0.5, B: 0.43, id: 2, dummy: 1, }, ]; 

const inputs = { arr1, arr2, arr3 };

const result = Object.values(Object.entries(inputs).reduce((acc, [key, arr]) => { 
    return arr.reduce((acc, { id, dummy, ...obj}) => {
        acc[id] = acc[id] || { id, dummy };
        for(let prop in obj) {
            acc[id][`${key}_${prop}`] = obj[prop];
        }
        if (dummy !== acc[id].dummy) {
            acc[id].dummy = '-';
        }
        return acc;
    }, acc);
}, {}))

console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }

Upvotes: 1

codeburst
codeburst

Reputation: 128

The same solution without map and reduce methods for old browsers as well

let arr1 = [
  { A: 0.71, B: 0.52, id: 1, dummy: 1, },
  { A: 0.72, B: 0.50, id: 2, dummy: 1, },
];
let arr2 = [
  { A: 0.157,   B: 0.02255,  id: 1, dummy: 1, },
  { A: 0.16761, B: 0.028281, id: 2, dummy: 1, },
];
let arr3 = [
  { A: 0.55, B: 0.50, id: 1, dummy: 1, },
  { A: 0.5,  B: 0.43, id: 2, dummy: 1, },
];

let finalArr = []
let keysToUse = ['id', 'dummy'];
let countOfIds = arr1.length;
let ids = arr1.map(d => d.id);
let varArrayToUse = ['arr1', 'arr2', 'arr3'];
// console.log('len '+countOfIds)

for(var i = 0; i < ids.length; i++){
    finalArr[i] = {
        id: arr1[i].id,
        dummy: arr1[i].dummy,
    }

    for(var j = 0; j < varArrayToUse.length; j++) {
        if (j == 0) { targetArr = arr1 } else if (j == 1) {targetArr = arr2} else {targetArr = arr3}
        finalArr[i][varArrayToUse[j]] =  
            {
                A: (targetArr[i]).A,
                B: (targetArr[i]).B
            }                
    }
}
console.log(finalArr)

Upvotes: 1

Related Questions