0

My Problem:

I'm having a website where I can compare products stored inside an array (with objects). I want to add different filters from array inside of an object that get applied together.

For two filters I can easily do it (see my code below). I just compare two objects and use a filter depending on their content.

But what would be a good approach to use the filter if there are more than two objects. Can I loop through the object and compare if the arrays are empty?

With my current approach I would have to extend my code for every new filter and it would balloon.

What I'm trying to do:

I want to check which filter objects have any data in their "feature" array (that array gets filled after the user clicks a filter on the site) and if they have I want to use these arrays to filter the main filteredArray array.

My current Object:

features_collection: {
    aspect_ratio_object: {
      features: [],
      value: "Aspect Ratio",
    },
    performance_rating_object: {
      features: [],
      value: "Performance Rating",
    },
  },

My Filter Function:

    if (
      features_collection.aspect_ratio_object.features.length &&
      features_collection.performance_rating_object.features.length
    ) {
      return filteredArray.filter(
        (obj) =>
          features_collection.aspect_ratio_object.features.includes(
            obj[features_collection.aspect_ratio_object.value]
          ) &&
          features_collection.performance_rating_object.features.includes(
            obj[features_collection.performance_rating_object.value]
          )
      );
    } else if (
      features_collection.aspect_ratio_object.features.length ||
      features_collection.performance_rating_object.features.length
    ) {
      return filteredArray.filter(
        (obj) =>
          features_collection.aspect_ratio_object.features.includes(
            obj[features_collection.aspect_ratio_object.value]
          ) ||
          features_collection.performance_rating_object.features.includes(
            obj[features_collection.performance_rating_object.value]
          )
      );
    }
  },

Further Notes:

I can also change my object. I could change it into an array of objects if that would make things easier?

2
  • How does the array you're trying to filter look like? Commented Feb 8, 2022 at 16:03
  • It is like this: filtered_items: [ { AspectRatio: "4:3", PerformanceRating: "good" }, { AspectRatio: "5:3", PerformanceRating: "perfect" }, { AspectRatio: "16:9", PerformanceRating: "better" }, { AspectRatio: "4:3", PerformanceRating: "perfect" }, ], An array of objects Commented Feb 8, 2022 at 16:15

2 Answers 2

1

Making your filters an array seems more practical. Here's an example on how to filter a set of objects against your feature_collection.

function filter_by_features(targets, feature_collection) {
    
    // Start right of to filter the `filteredArray`
    return targets.filter(obj => {

        // go through every feature and test it against the current object.
        // every() returns either true or false and the targets array is filtered 
        // by that condition supplied within the callback of `every()`
        return feature_collection.every(filter => {

            // If for a given feature no filter is available, return true
            // so the test for this filter passes.
            if(filter.features.length === 0) {
                return true
            }

            // there are features, check if any applies.
            return filter.features.includes(obj[filter.value])
    
        })

    })

}

Usage

// feature collection  (as array)
const feature_collection = [
    {
        features: [],
        value: "Aspect Ratio",
    },
    {
        features: [],
        value: "Performance Rating",
    }
]

// the objects you want to filter.
const objects_to_filter = [/* ... */]

const filtered = filter_by_features(objects_to_filter, feature_collection)

docs

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

2 Comments

Wow thank you, that's amazing. It worked very well. I have a question about the every() method if you don't mind. The code basically checks if the "targets" array of objects contains objects where any value inside the array "filter.features" matches the value for "filter.value" in any targets object. And then returns the object? So the every method only stops when it looked at all elements in an array. But what is the actual filter test for "targets.filter..." from: "return feature_collection.every(...)"? Is every just true or false and if it's true then that passes the targets.filter?
every() returns either true if the specified condition in the callback is fullfilled for every element and otherwise returns false . So for each object check all the filters. If that did not answer your question go ahead and edit your main question so I can do a detailed edit to my answer ..
1

You obviously have too loop through your object.

Here is your loop code for features_collection:

features_collection.forEach(function (item, index) {
  console.log(item, index);
});

2 Comments

Thank you! I'll try to work with it :)
forEach is only for arrays. features_collection in the question is an object, and not an array.

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.