0

Been racking my head for a few nights now and Im hoping a kind soul can help solve this wall I have hit.

I have an Array of Objects.

As a user I should be able to filter feature name(s) by multiple or singular filters. A single filter should return all events with a matching name A multiple filter should match all events with more than one feature name, not less than 2 or the length of the filters array.

The code I have eventually been stuck with or as far as I can go is this.

let obj1 = [{
  "results": [{
      "id": "1",
      "name": "Event 1",
      "feature": [{
          "id": {
            "target": "78"
          },
          "name": "Bronze"
        },
        {
          "id": {
            "target": "27"
          },
          "name": "Straw"
        },
        {
          "id": {
            "target": "45"
          },
          "name": "Gold"
        }
      ]
    },
    {
      "id": "2",
      "name": "Event 2",
      "feature": [{
        "id": {
          "target": "20"
        },
        "name": "Straw"
      }]
    },
    {
      "id": "3",
      "name": "Event 3",
      "feature": [{
          "id": {
            "target": "20"
          },
          "name": "Gold"
        },
        {
          "id": {
            "target": "20"
          },
          "name": "Straw"
        }
      ]
    },
    {
      "id": "4",
      "name": "Event 4",
      "feature": [{
          "id": {
            "target": "97"
          },
          "name": "Coal"
        },
        {
          "id": {
            "target": "39"
          },
          "name": "Wood"
        }
      ]
    }
  ]
}]


let filterQuery = ['Straw', 'Gold'];


obj1 = obj1[0].results.filter(r => {
  return r.feature.every(f => {
    return filterQuery.includes(f.name)
  })
})

console.log(obj1);

It filters anything with Straw or Gold, and everything with Straw and Gold

Im trying to get the filter to filter Straw && Gold

So returning an event(s) with example

{name: 'Straw', name: 'Gold', name: 'Diamond', name: Copper}

would be a correct match, so a user could add another filter to the array to filter the results further.

{ name: Straw, name: Diamond }

Would not be a correct match.

Any help, suggestions would be greatly appreciated :)

===========================================================

Updated, solved solution. I needed it to be agnostic as possible so it works if key names change. Used in a Vuejs project with Drupal.

    export default class FilterData {
    
      constructor(name, data, filter_query) {
        this.name = name;
        this.data = data;
        this.filter_query = filter_query;
      }
    
      filterData(){
        let temp = this.data

// filter out any undefined arrays
        temp = temp.filter((item) => item[this.name] !== undefined);
        temp = temp.filter((item) =>
          [this.filter_query].every((filter) =>
            item[this.name].some(({ name }) => name === filter)
          )
        );
        return temp
      }
    
    }

And use it like so

/* use a temp copy of the returned data from the api
so we can keep refiltering from multiple drop downs, radio, checkboxes changes each time a filter keyname is un-selected.
*/

let apiResults = this.apiData.results;

      let filtered = new FilterData(
        `${keyname}`,
        apiResults,
        this.filterQuery[`${keyname}`]
      );

Thank you so much @pilchard your answer helped this greatly.

1
  • What's the difference between your first two paragraphs below your code sample? Straw and Gold vs. Straw && Gold Commented Feb 8, 2022 at 0:41

1 Answer 1

2

You need to switch your every() call to the filterQuery array. So test if every() string in the filter array has a match in the feature array, here testing with some().

let obj1 = [{ "results": [{ "id": "1", "name": "Event 1", "feature": [{ "id": { "target": "78" }, "name": "Bronze" }, { "id": { "target": "27" }, "name": "Straw" }, { "id": { "target": "45" }, "name": "Gold" }] }, { "id": "2", "name": "Event 2", "feature": [{ "id": { "target": "20" }, "name": "Straw" }] }, { "id": "3", "name": "Event 3", "feature": [{ "id": { "target": "20" }, "name": "Gold" }, { "id": { "target": "20" }, "name": "Straw" }] }, { "id": "4", "name": "Event 4", "feature": [{ "id": { "target": "97" }, "name": "Coal" }, { "id": { "target": "39" }, "name": "Wood" }] }] }]

let filterQuery = ['Straw', 'Gold'];

const filteredObj = obj1[0].results.filter(({ feature }) =>
  filterQuery.every(filter =>
    feature.some(({ name }) => name === filter)))

console.log(filteredObj);

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

Comments

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.