Home > Blockchain >  Check only the properties that two objects have in common. Return every object with matching propert
Check only the properties that two objects have in common. Return every object with matching propert

Time:12-21

I'm writing a filter to show only certain elements based on keywords. So I have an array of objects in this key/pair format:

name: "Accounting (AAS) | Business, Design & Hospitality Pathway",
type: "associate of arts",
method: "classroom based",
location: "centennial campus",
pathway: "business, design, & hospitality",
time: "4 semesters",
transfer: "transferable"

I have an object I'm creating from the radio buttons. It's called selectedFilters. If only one radio is checked it would return this:

{type: 'associate of arts'}

If two radios are checked:

{type: 'associate of arts', method: 'hyflex class'}

So the second object doesn't have all the properties of the first object. I need to check if the properties they do have in common match. So if the object created by the radio buttons has two properties. I only want the objects to return if both properties match.

I have an if statement in my forEach loop. But it only returns if every property matches. Can someone find a solution so I'm only pushing the objects where the properties that exist match?

data.forEach(function(el) {
    if (
      el.type == selectedFilters.type &&
      el.method == selectedFilters.method &&
      el.location == selectedFilters.location &&
      el.pathway == selectedFilters.pathway &&
      el.time == selectedFilters.time &&
      el.transfer == selectedFilters.transfer
    ) {
      result.push(el);
    };
  });

CodePudding user response:

Use Object.entries() and Array.every() to filter the entries from the radio object against the data array

const radioObj = {
  A: 1,
  C: 2
},
radioEntries =  Object.entries(radioObj),
data = [{
    A: 1,
    B: 3,
    C: 2
  },
  {
    A: 2,
    B: 2,
    C:2
  }

]



const res = data.filter(e => radioEntries.every(([k,v]) => e[k] === v))

console.log(res)

CodePudding user response:

First off, radio buttons will only have one possible selection. You're looking for check boxes.

Now, If I understand your problem correctly, you're going wrong because you're always checking every property in your candidate object. What you need to do is iterate through your "object you're creating from the radio buttons" (selectedFilters in my example code), checking whether the value of each of those properties equals the value in your candidate object.

Here's an example:

    let objs = [
      {
        name: "Accounting (AAS) | Business, Design & Hospitality Pathway",
        type: "associate of arts",
        method: "classroom based",
        location: "centennial campus",
        pathway: "business, design, & hospitality",
        time: "4 semesters",
        transfer: "transferable"
      },
      {
        name: "Accounting (AAS) | Business, Design & Hospitality Pathway",
        type: "associate of arts",
        method: "classroom based",
        location: "centennial campus",
        pathway: "art, music and history",
        time: "4 semesters",
        transfer: "transferable"
      },
      {
        name: "Accounting (AAS) | Business, Design & Hospitality Pathway",
        type: "associate of science",
        method: "classroom based",
        location: "centennial campus",
        pathway: "business, design, & hospitality",
        time: "4 semesters",
        transfer: "transferable"
      },
    ]  

    let selectedFilters = {
      type: "associate of arts",
      method: "classroom based",
    }

    function checkObj(obj, selectedFilters) {
      for (x in selectedFilters) {
        if (obj[x] !== selectedFilters[x]) return false;
      }

      return true;
    }

    let result = [];
    for (obj of objs) {
      if (checkObj(obj, selectedFilters)) result.push(obj)
    }
    console.log(result);

In the test, I'm using selectedFilters with two selected properties. Of the objects in the array, the third one shouldn't be selected because the type property is different. So, the checkObj function just runs through the selectedFilters properties and compares them to the object passed in. Since it's iterating through the check object, it ignores any properties that the check object doesn't have.

So, you loop through the array of candidate objects, calling the objCheck function for each one. Whenever the function returns true (because all the properties in selectedFilters match the same properties in the candidate object, ignoring any properties that aren't in selectedFilters), the object gets pushed into the result array.

CodePudding user response:

You can map the object like so

const data = [{
    name: "Accounting (AAS) | Business, Design & Hospitality Pathway",
    type: "associate of arts",
    method: "classroom based",
    location: "centennial campus",
    pathway: "business, design, & hospitality",
    time: "4 semesters",
    transfer: "transferable"
}]

const selectedFilters = {
    type: 'associate of arts',
    transfer: "transferable"
}

const res = data.reduce((acc, entry) => {
    // for each key in filter check if the value of the entry matches the filter value
    // only do the check if the filter value has not been set to false
    // if all filter values pass push the object, else just return the original array
        return Object
            .keys( selectedFilters )
            .reduce( ( ok, key ) => {
                return ok ? selectedFilters[key] === entry[key] : false;
            }, true ) ? acc.concat( entry ) : acc;
    }
    , [])

console.log(res);

  • Related