NigelDcruz
NigelDcruz

Reputation: 927

How to filter through a JavaScript array using array.filter() method?

I have a JavaScript Object (filters), which has boolean values. I also have an array of objects (mainSubArray). Based on the JavaScript Object, I want to return a new array (filteredArray) if the boolean values are true and not return a new array if the boolean value is false.

So far, I've tried the following:

// The main array that needs to be filtered
const mainSubArray = [{
    MenB_Classification: "NOT Required",
    CONTROL: "Public",
    Enrollment: "892"
  },
  {
    MenB_Classification: "Required",
    CONTROL: "Private",
    Enrollment: "1601"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "447"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Public",
    Enrollment: "1203"
  },
  {
    MenB_Classification: "Required",
    CONTROL: "Private",
    Enrollment: "32"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Public",
    Enrollment: "98"
  },
  {
    MenB_Classification: "Recommended",
    CONTROL: "Private",
    Enrollment: "654"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "345318"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "13324"
  },
  {
    MenB_Classification: "Recommended",
    CONTROL: "Private",
    Enrollment: "39"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "4"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "910"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "23453"
  }
]


// Object with boolean values
var filters = {
  required: true,
  recomended: true,
  notRequired: false,
  publics: true,
  privates: true,
  ennrollmentOne: true,
  ennrollmentTwo: false,
  ennrollmentThree: false,
  ennrollmentFour: false,
}

// New Array using array.filter() method
var filteredArray = mainSubArray.filter(function(d) {
  if ((filters.required == true && d.MenB_Classification === 'Required') || (filters.recomended === true && d.MenB_Classification === 'Recommended') || (filters.notRequired === true && d.MenB_Classification === 'NOT Required') || (filters.publics === true && d.CONTROL === 'Public') || (filters.privates === true && d.CONTROL === 'Private') || (filters.ennrollmentOne === true && d.Enrollment < 100) || (filters.ennrollmentTwo === true && d.Enrollment >= 100 && d.Enrollment < 1000) || (filters.ennrollmentThree === true && d.Enrollment >= 1000 && d.Enrollment < 5000) || (filters.ennrollmentThree === true && d.Enrollment > 5000)) {
    return true;
  } else {
    return false;
  }

});

console.log(filteredArray);

When I console.log(filteredArray) , I get back the original array.

The output should be a new array that has only the values that are set to true in the filters object.

Upvotes: 0

Views: 106

Answers (4)

Nina Scholz
Nina Scholz

Reputation: 386560

You could take an array of strings for the keys of the filter object and according function for checking the wanted keys of the object with their wanted value/s.

In the filter function iterate key function array and exit early if a function is wanted and the result is true.

The result is an array of 12 object from original 13 objects.

var data = [{ MenB_Classification: "NOT Required", CONTROL: "Public", Enrollment: "892" }, { MenB_Classification: "Required", CONTROL: "Private", Enrollment: "1601" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "447" }, { MenB_Classification: "NOT Required", CONTROL: "Public", Enrollment: "1203" }, { MenB_Classification: "Required", CONTROL: "Private", Enrollment: "32" }, { MenB_Classification: "NOT Required", CONTROL: "Public", Enrollment: "98" }, { MenB_Classification: "Recommended", CONTROL: "Private", Enrollment: "654" }, { MenB_Classification: "NOT Required", CONTROL: "33033764030", Enrollment: "345318" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "13324" }, { MenB_Classification: "Recommended", CONTROL: "Private", Enrollment: "39" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "4" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "910" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "23453" }],
    filters = {
        required: true,
        recomended: true,
        notRequired: false,
        publics: true,
        privates: true,
        ennrollmentOne: true,
        ennrollmentTwo: false,
        ennrollmentThree: false,
        ennrollmentFour: false,
    },
    fn = [
        ['required', o => o.MenB_Classification === 'Required'],
        ['recomended', o => o.MenB_Classification === 'Recommended'],
        ['notRequired', o => o.MenB_Classification === 'NOT Required'],
        ['publics', o => o.CONTROL === 'Public'],
        ['privates', o => o.CONTROL === 'Private'],
        ['ennrollmentOne', o => o.Enrollment < 100],
        ['ennrollmentTwo', o => o.Enrollment >= 100 && o.Enrollment < 1000],
        ['ennrollmentThree', o => o.Enrollment >= 1000 && o.Enrollment < 5000],
        ['ennrollmentFour', o => o.Enrollment >= 5000]
    ],
    result = data.filter(o => fn.some(([k, f]) => filters[k] && f(o)));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 2

Thomas
Thomas

Reputation: 12637

I assume you want to do this:

var data = [{ MenB_Classification: "NOT Required", CONTROL: "Public", Enrollment: "892" }, { MenB_Classification: "Required", CONTROL: "Private", Enrollment: "1601" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "447" }, { MenB_Classification: "NOT Required", CONTROL: "Public", Enrollment: "1203" }, { MenB_Classification: "Required", CONTROL: "Private", Enrollment: "32" }, { MenB_Classification: "NOT Required", CONTROL: "Public", Enrollment: "98" }, { MenB_Classification: "Recommended", CONTROL: "Private", Enrollment: "654" }, { MenB_Classification: "NOT Required", CONTROL: "33033764030", Enrollment: "345318" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "13324" }, { MenB_Classification: "Recommended", CONTROL: "Private", Enrollment: "39" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "4" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "910" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "23453" }],
    filters = {
        required: true,
        recomended: true,
        notRequired: false,
        publics: true,
        privates: true,
        ennrollmentOne: true,
        ennrollmentTwo: false,
        ennrollmentThree: false,
        ennrollmentFour: false,
    },
    filteredArray = data.filter(function (d) {
      return ( // check MenB_Classification
           (filters.required && d.MenB_Classification === "Required")
        || (filters.recomended && d.MenB_Classification === "Recommended")
        || (filters.notRequired && d.MenB_Classification === "NOT Required")
      ) && ( // check CONTROL
           (filters.publics && d.CONTROL === "Public")
        || (filters.privates && d.CONTROL === "Private")
      ) && ( // check Enrollment
           (filters.ennrollmentOne && d.Enrollment < 100)
        || (filters.ennrollmentTwo && d.Enrollment >= 100 && d.Enrollment < 1000)
        || (filters.ennrollmentThree && d.Enrollment >= 1000 && d.Enrollment < 5000)
        || (filters.ennrollmentFour && d.Enrollment > 5000)
      );
    });

console.log(filteredArray);

Here a more verbose version. I've seperated the filter into one function for each property:

And I don't know wether this is relevant for you, but I've also added the case when there is no filter set for a property.

function filterByClassification(d){
    return (filters.required && d.MenB_Classification === "Required")
        || (filters.recomended && d.MenB_Classification === "Recommended")
        || (filters.notRequired && d.MenB_Classification === "NOT Required")
        // or no filter set for MenB_Classification
        || (!filters.required && !filters.recomended && !filters.notRequired);
}

function filterByControl(d){
    return (filters.publics && d.CONTROL === "Public")
        || (filters.privates && d.CONTROL === "Private")
        // or no filter set for CONTROL
        || (!filters.publics && !filters.privates);
}

function filterByEnrollment(d){
    return (filters.ennrollmentOne && d.Enrollment < 100)
        || (filters.ennrollmentTwo && d.Enrollment >= 100 && d.Enrollment < 1000)
        || (filters.ennrollmentThree && d.Enrollment >= 1000 && d.Enrollment < 5000)
        || (filters.ennrollmentFour && d.Enrollment > 5000)
        // or no filter set for Enrollment
        || (!filters.ennrollmentOne && !filters.ennrollmentTwo && !filters.ennrollmentThree && !filters.ennrollmentFour); 
}


filteredArray = data.filter(function (d) {
    // for every property, there must be one filter fulfilled
    return filterByClassification(d) 
        && filterByControl(d) 
        && filterByEnrollment(d);
});

while your code was equivalent to:

filteredArray = data.filter(function (d) {
    // if any condition at all is fulfilled, keep the item
    return filterByClassification(d) 
        || filterByControl(d) 
        || filterByEnrollment(d);
});`

Upvotes: 1

Bilal Siddiqui
Bilal Siddiqui

Reputation: 3629

No, the filteredArray isn't same as main array. You can log the length to feel the difference easily.

Also, if else can be avoided to use a return on all condition only.

// The main array that needs to be filtered
const mainSubArray = [{
    MenB_Classification: "NOT Required",
    CONTROL: "Public",
    Enrollment: "892"
  },
  {
    MenB_Classification: "Required",
    CONTROL: "Private",
    Enrollment: "1601"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "447"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Public",
    Enrollment: "1203"
  },
  {
    MenB_Classification: "Required",
    CONTROL: "Private",
    Enrollment: "32"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Public",
    Enrollment: "98"
  },
  {
    MenB_Classification: "Recommended",
    CONTROL: "Private",
    Enrollment: "654"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "33033764030",
    Enrollment: "345318"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "13324"
  },
  {
    MenB_Classification: "Recommended",
    CONTROL: "Private",
    Enrollment: "39"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "4"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "910"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "23453"
  }
]


// Object with boolean values
var filters = {
  required: true,
  recomended: true,
  notRequired: false,
  publics: true,
  privates: true,
  ennrollmentOne: true,
  ennrollmentTwo: false,
  ennrollmentThree: false,
  ennrollmentFour: false,
}

// New Array using array.filter() method
var filteredArray = mainSubArray.filter(function(d) {
  return ((filters.required && d.MenB_Classification === 'Required') || (filters.recomended && d.MenB_Classification === 'Recommended') || (filters.notRequired && d.MenB_Classification === 'NOT Required') || (filters.publics && d.CONTROL === 'Public') || (filters.privates && d.CONTROL === 'Private') || (filters.ennrollmentOne && d.Enrollment < 100) || (filters.ennrollmentTwo && d.Enrollment >= 100 && d.Enrollment < 1000) || (filters.ennrollmentThree && d.Enrollment >= 1000 && d.Enrollment < 5000) || (filters.ennrollmentThree && d.Enrollment > 5000));
});
console.log(mainSubArray.length)
console.log(filteredArray.length);

Upvotes: -1

Alex Vovchuk
Alex Vovchuk

Reputation: 2926

It works, but your conditions cover almost all cases.

Even in your case it works as result contains 12 elements instead of 13. It doesn't contain:

{
    MenB_Classification: "NOT Required",
    CONTROL: "33033764030",
    Enrollment: "345318"
  },

Upvotes: 1

Related Questions