0

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,
  },
];
7
  • What if the value of dummy differs for same id? Commented Dec 8, 2022 at 6:55
  • dummy value can be any integer. Commented Dec 8, 2022 at 6:58
  • What about naming the arrays in your finalArr? arr followed by a consecutive number? Commented Dec 8, 2022 at 6:58
  • If the dummy can be any integer than your desired output cannot hold multiple dummy values per id Commented Dec 8, 2022 at 6:59
  • per id, there is only one dummy value. (eg. id:1 dummy:7 now this will be the same for all three arrays having id: 1) Commented Dec 8, 2022 at 7:16

3 Answers 3

2

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

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

Comments

1

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

Comments

1

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.