0

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.

9
  • 1
    I tried your code and it looks original array mainSubArray has 13 items , filtered array filteredArray has 12 items inside , difference is {MenB_Classification: "NOT Required", CONTROL: "33033764030", Enrollment: "345318"} Commented Oct 8, 2019 at 15:23
  • what is filters doing? why it does not have vlaues who are directly comparable with the object's values? Commented Oct 8, 2019 at 15:25
  • What do you want the filtered array to look like? Right now I think the issue is with your logic, since you are using 9 or 10 different or statements it is almost always matching one of them. I would also suggest writing someBoolean && instead of someBoolean === true &&. Commented Oct 8, 2019 at 15:30
  • Your if condition inside filter function covers everything and that's why you see the original array as result of filter Commented Oct 8, 2019 at 15:30
  • So, if ANY of the filters is true, include the item !? Or should it only include items where all filters apply? Commented Oct 8, 2019 at 15:32

4 Answers 4

2

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

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

Comments

1

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"
  },

1 Comment

It is just confirmation that issue doesn't exist. Initial solution works fine. Other code is just to make it more elegant
1

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

3 Comments

I'm having difficulty figuring out the difference in our code and why your code worked and mine didn't. Anyway, thank you. This is exactly what I wanted.
@NigelDcruz I was a bit in a hurry. I group the conditions by property. At least one condition for each property has to be true. Your code just asked if any condition was fulfilled. So if filters.required was fulfilled, it didn't care anymore about the filters for CONTROL or Enrollment.
@NigelDcruz I've added a more verbose example
-1

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

1 Comment

@TylerRoper Hey man, it wasn't an issue but a confusion instead. Suggestion of logging lengths on console is a solution to remove his confusion . :)

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.