Home > Back-end >  Compare Two Arrays of Objects To get All Elements of First Present in Second
Compare Two Arrays of Objects To get All Elements of First Present in Second

Time:11-20

I have the following two arrays of objects and I want to filter all elements of first array whose "stage" value is same in any of the element of second array.

const arr1 = [
  {
    id: '1',
    name: 'Ahmad',
    title: 'Manager',
    stage: 'Open',
  },
  {
    id: '2',
    name: 'Ahmad',
    title: 'Manager',
    stage: 'Open',
  },
  {
    id: '3',
    name: 'Ahmad',
    title: 'Manager',
    stage: 'Open',
  },
  {
    id: '4',
    name: 'Bakshi',
    title: 'Accountant',
    stage: 'Closed Won',
  },
  {
    id: '5',
    name: 'Rehmat',
    title: 'Chancellor',
    stage: 'Open',
  }];

const arr2 = [
  {id: '2', stage: 'Closed', selected: false},
  {id: '3', stage: 'Closed Won', selected: false},
  {id: '4', stage: 'Open Won', selected: false},
  {id: '5', stage: 'Completed', selected: false},
  {id: '1', stage: 'Open', selected: false}
  ];

I have used the following logic

const changedObjects = Object.keys(arr1).filter(index => arr1[index].stage === arr2[index].stage).map(index => arr1[index]);

But the problem here is that it only filters last element of arr1 which matches exactly with element of last index of arr2. I want it to display all elements of arr1 whose stage="Open".

I have tried multiple logic but still unable to get the required output

CodePudding user response:

The problem in your code is that it only checks objects on same index.

you need to check all objects inside arr2 and compare stage properties.

let filteredArr = arr1.filter((o1) => {
  return arr2.some((o2) => o2.stage === o1.stage);
});

CodePudding user response:

When you have no idea why your code is not working, the best way to slove it, is break it down into pieces and console.log every stage to see where it start to go wrong, which in you case:

const arr1 = [
  {id: '1',name: 'Ahmad',title: 'Manager',stage: 'Open',},
  {id: '2',name: 'Ahmad',title: 'Manager',stage: 'Open',},
  {id: '3',name: 'Ahmad',title: 'Manager',stage: 'Open',},
  {id: '4',name: 'Bakshi',title: 'Accountant',stage: 'Closed Won',},
  {id: '5',name: 'Rehmat',title: 'Chancellor',stage: 'Open',}
  ];

const arr2 = [
  {id: '2', stage: 'Closed', selected: false},
  {id: '3', stage: 'Closed Won', selected: false},
  {id: '4', stage: 'Open Won', selected: false},
  {id: '5', stage: 'Completed', selected: false},
  {id: '1', stage: 'Open', selected: false},
  ];

const objectKeysOfarr1 = Object.keys(arr1);
console.log(`objectKeysOfarr1: ${objectKeysOfarr1}`);
/**
output:
objectKeysOfarr1: 0,1,2,3,4
*/

const filterObjectKeysOfarr1 = objectKeysOfarr1
  .filter(index => {
    console.log(`arr1[index].stage: ${arr1[index].stage}`);
    console.log(`arr2[index].stage: ${arr2[index].stage}`);
    console.log(`arr1[index].stage === arr2[index].stage: ${arr1[index].stage === arr2[index].stage}`);
    return arr1[index].stage === arr2[index].stage;
  });
console.log(`filterObjectKeysOfarr1: ${filterObjectKeysOfarr1}`);
/**
output:
  arr1[index].stage: Open
  arr2[index].stage: Closed
  arr1[index].stage === arr2[index].stage: false
  arr1[index].stage: Open
  arr2[index].stage: Closed Won
  arr1[index].stage === arr2[index].stage: false
  arr1[index].stage: Open
  arr2[index].stage: Open Won
  arr1[index].stage === arr2[index].stage: false
  arr1[index].stage: Closed Won
  arr2[index].stage: Completed
  arr1[index].stage === arr2[index].stage: false
  arr1[index].stage: Open
  arr2[index].stage: Open
  arr1[index].stage === arr2[index].stage: true
  filterObjectKeysOfarr1: 4
*/

const changedObjects = filterObjectKeysOfarr1
  .map(index => {
    console.log(`arr1[index]: ${JSON.stringify(arr1[index])}`);
    return arr1[index];
  });
console.log(`changedObjects: ${JSON.stringify(changedObjects)}`);
/**
output:
  arr1[index]: {"id":"5","name":"Rehmat","title":"Chancellor","stage":"Open"}
  changedObjects: [{"id":"5","name":"Rehmat","title":"Chancellor","stage":"Open"}]
*/

// As shown in the log, the reason why you are only getting one output, is beacuse the filter you write compares only the object of the same index in 'arr1' and 'arr2', which apparently won't return all 'Open stage' of the arr1.
// actually, you don't need to compare two arrays if you are only trying to get all 'Open stage' from 'arr1', such as:

const result1 = arr1.filter(o => o.stage === 'Open');
console.log(`get all open:\n${JSON.stringify(result1)}`);
/**
output:
  get all open:
  [
    {"id":"1","name":"Ahmad","title":"Manager","stage":"Open"},
    {"id":"2","name":"Ahmad","title":"Manager","stage":"Open"},
    {"id":"3","name":"Ahmad","title":"Manager","stage":"Open"},
    {"id":"5","name":"Rehmat","title":"Chancellor","stage":"Open"}
  ]
*/

// let's say if what you want to do is to compare arr1 with arr2 which the stage of arr1 is 'included' in selected stages of arr2, this is how you should do:

// triggerStage(): trigger true/false switch of the 'select' value of the object of the given ID, accept 'id' as number, string or array.
const triggerStage = (arr,id) => {
  let ids = [];
  if (!Array.isArray(id)) ids.push(id);
  else ids = id;
  return arr.map(o => ids.some(id => id == o.id) ? (o.selected = !o.selected) && o : o);
}

// selectedStages(): returns an array of the 'stage' that is being selected.
const selectedStages = (arr) => arr.filter(o => o.selected).map(o => o.stage);

// the follow example shows switching on id:1 and 2.
const newArr2 = triggerStage(arr2,[1,'2']);
console.log(`newArr2:\n${JSON.stringify(newArr2)}`);
/**
output:
  newArr2:
  [
    {"id": "2","stage": "Closed","selected": true},
    {"id": "3","stage": "Closed Won","selected": false},
    {"id": "4","stage": "Open Won","selected": false},
    {"id": "5","stage": "Completed","selected": false},
    {"id": "1","stage": "Open","selected": true}
  ]
*/

const selected = selectedStages(newArr2);
console.log(`selected: ${JSON.stringify(selected)}`);

/**
output: selected: ["Closed","Open"]
*/

// filter 'arr1' to for objects which the 'stage' matches the 'selected' stage of 'arr2':
const result2 = arr1.filter(o => selected.some(stage => stage === o.stage));
console.log(`result2:\n${JSON.stringify(result2)}`);
/**
output:
  result2:
  [
    {"id":"1","name":"Ahmad","title":"Manager","stage":"Open"},
    {"id":"2","name":"Ahmad","title":"Manager","stage":"Open"},
    {"id":"3","name":"Ahmad","title":"Manager","stage":"Open"},
    {"id":"5","name":"Rehmat","title":"Chancellor","stage":"Open"}
  ]
*/

  • Related