Josh
Josh

Reputation: 1235

Trying to compare two arrays of objects and remove matching elements from one array and return it, currently only removing first match

I have a filterSection object array and a customFilter array and I'm trying to loop through both and remove any matching elements from the filterSection array.

The problem I'm running into is that I can only seem to remove the first match and nothing beyond that and I'm not sure what I'm doing wrong.

This is my function for compare/remove:

const newFilterList = (filterSelection) => {
    for( var i = 0; i < filterSelection.length; i++){
      for( var j = 0; j < customFilter.length; j++) 
        if ( filterSelection[i].section === customFilter[j].section) { 
          return filterSelection = filterSelection.splice(i, 1); 
        }
  }
}

And these are my two object arrays:

customFilter

[
 {
  section: 'Artists',
  filters: ['LVNDMARKS']
 },
 {
   section: 'Years',
   filters: ['2021']
 }
]

And my filterSelection is this:

[
 {
   section: 'Artists',
   filters: ['LVNDMARKS', 'Born of Osiris', 'Intervals']
 },
 {
   section: 'Years',
   filters: ['2021','2019','2017']
 },
 {
  section: 'Albums',
  filters: ['albumName', 'albumName', 'albumName',]
 }
]

Upvotes: 1

Views: 101

Answers (5)

Raishav Hanspal
Raishav Hanspal

Reputation: 111

Here is a different approach. To store the indexes and splice them afterward.

const newFilterList = (filterSelection) => { 
    let indexToRemove = [];
    let customFilterArray = [];
    for(let temp of customFilter)
        customFilterArray.push(temp.section);
    filterSelection.forEach((el,index)=>{
        if(customFilterArray.includes(el.section))
            indexToRemove.push(index)
    })
  while(indexToRemove.length>0) 
    {
      filterSelection.splice(indexToRemove[indexToRemove.length - 1],1);
      indexToRemove.pop();
    }
   }

Upvotes: 0

Miki
Miki

Reputation: 1818

Try this:

const data = [
  {
    sec: "Artists",
    fil: ["LVNDMARKS", "Born of Osiris", "Intervals"]
  },
  {
    sec: "Years",
    fil: ["2021", "2019", "2017"]
  },
  {
    sec: "Albums",
    fil: ["albumName", "albumName", "albumName"]
  }
];
const conditions = [
  {
    sec: "Artists",
    fil: ["LVNDMARKS"]
  },
  {
    sec: "Years",
    fil: ["2021"]
  }
];

conditions.forEach(cond => {
  data
    .filter(el => el.sec == cond.sec)
    .forEach(match => {
      match.fil = match.fil
        .filter(filEl => cond.fil.indexOf(filEl) == -1);
      console.log(match.fil);
    });
});

I've renamed your objects as it was quite confusing mixing "filter" the property and "filter" the array operator.

Adding codepen for convenience.

Upvotes: 2

Rex Henderson
Rex Henderson

Reputation: 412

let customFilter = [
 {
  section: 'Artists',
  filters: ['LVNDMARKS']
 },
 {
   section: 'Years',
   filters: ['2021']
 }
];

let filterSelection = [
 {
   section: 'Artists',
   filters: ['LVNDMARKS', 'Born of Osiris', 'Intervals']
 },
 {
   section: 'Years',
   filters: ['2021','2019','2017']
 },
 {
  section: 'Albums',
  filters: ['albumName', 'albumName', 'albumName',]
 }
];

let newFilter = [];

filterSelection.forEach(i => {  
  if(!customFilter.some(ii => ii.section === i.section))
    newFilter.push(i);
});

console.log(newFilter);

Upvotes: 0

Baskaran Ajiharan
Baskaran Ajiharan

Reputation: 508

don't use a return statement because it terminates your loop when the if condition true for the first time. so you can easily push matching data in an array & return it

    const customFilter = [
        {
          section: "Artists",
          filters: ["LVNDMARKS"]
        },
        {
          section: "Years",
          filters: ["2021"]
        }
      ];
      const filterSelection = [
        {
          section: "Artists",
          filters: ["LVNDMARKS", "Born of Osiris", "Intervals"]
        },
        {
          section: "Years",
          filters: ["2021", "2019", "2017"]
        },
        {
          section: "Albums",
          filters: ["albumName", "albumName", "albumName"]
        }
      ];
     
    const newFilterList = filterSelection => {
        let empty = [];
        for (var i = 0; i < filterSelection.length; i++) {
          for (var j = 0; j < customFilter.length; j++)
            if (filterSelection[i].section === customFilter[j].section) {
              
              empty.push(filterSelection.splice(i, 1));
            }
        }
        return empty;
      };
      
     console.log( newFilterList(filterSelection))

or

const customFilter = [
    {
      section: "Artists",
      filters: ["LVNDMARKS"]
    },
    {
      section: "Years",
      filters: ["2021"]
    }
  ];
  const filterSelection = [
    {
      section: "Artists",
      filters: ["LVNDMARKS", "Born of Osiris", "Intervals"]
    },
    {
      section: "Years",
      filters: ["2021", "2019", "2017"]
    },
    {
      section: "Albums",
      filters: ["albumName", "albumName", "albumName"]
    }
  ];
   
    const newFilterList = filterSelection => {
        let empty = [];
        filterSelection.forEach(({section},i)=>{
          customFilter.map(res=>{
            if(section===res.section){
              empty.push(filterSelection[i])
            }
          })
        })
        return empty;
      };
      
      console.log(newFilterList(filterSelection))

Upvotes: 1

JBaczuk
JBaczuk

Reputation: 14589

Two problems, you are returning on the first match, and you are mutating the original filterSelection array in the loop so the length changes and you don't iterate over the entire array. You should store it to a temporary array to avoid this problem. Something like this:

const newFilterList = (filterSelection) => {
  let newFilterSelection = []
  for (var i = 0; i < filterSelection.length; i++) {
    for (var j = 0; j < customFilter.length; j++) {
      if (filterSelection[i].section === customFilter[j].section) {
        newFilterSelection = filterSelection.splice(i, 1);
      }
    }
  }
  filterSelection = newFilterSelection
};

The expression i < filterSelection.length is evaluated at the beginning of each loop:

for ([initialization]; [condition]; [final-expression])
  statement

condition

An expression to be evaluated before each loop iteration. If this >expression evaluates to true, statement is executed. This conditional test is optional. If omitted, the condition always evaluates to true. If the expression evaluates to false, execution skips to the first expression following the for construct.

MDN Web Docs - For Loops

Upvotes: 1

Related Questions