简体   繁体   中英

How to chain multiple filter functions in javascript with multiple conditions array

I have an array of data containing multiple properties, that needs to be filtered out via select boxes. Just like an eCommerce site where you can select a category, then certain sizes, then prices, then colors, etc.etc. all the filters combined, give a result.

How can I filter down on multiple properties and eventually return data that only contains the selected values? http://jsfiddle.net/Jeffwise/z2y41k85/3/

var vm = new Vue({
  el: '#root',
  data: {
    list: [{
        name: 'asd',
        category: 1
      },
      {
        name: 'zxc',
        category: 1
      },
      {
        name: 'qwe',
        category: 1
      },
      {
        name: 'qqq',
        category: 2
      },
      {
        name: 'www',
        category: 2
      },
      {
        name: 'eee',
        category: 2
      },
      {
        name: 'rrr',
        category: 2
      },
      {
        name: 'ttt',
        category: 2
      },
      {
        name: 'ert',
        category: 1
      },
      {
        name: 'wer',
        category: 2
      },
      {
        name: 'sdf',
        category: 1
      },
      {
        name: 'dfg',
        category: 2
      },
      {
        name: 'xcv',
        category: 1
      }
    ],
    categories: [{
        id: 1,
        name: 'cat 1'
      },
      {
        id: 2,
        name: 'cat 2'
      }
    ],
    keyword: 'e',
    category: 1
  },

  computed: {
    filteredByAll() {
      return getByCategory(getByKeyword(this.list, this.keyword), this.category)
    },
    filteredByKeyword() {
      return getByKeyword(this.list, this.keyword)
    },
    filteredByCategory() {
      return getByCategory(this.list, this.category)
    }
  }
});

function getByKeyword(list, keyword) {
  const search = keyword.trim()
  if (!search.length) return list
  return list.filter(item => item.name.indexOf(search) > -1)
}

function getByCategory(list, category) {
  if (!category) return list
  return list.filter(item => item.category === category)
}

I think what I am searching for is chaining multiple filtered functions together. But how do you do that? This js fiddle comes close, but how can you add more filters to this, so you can check for more functions/filters? I have a total of 10 filters that should 'work' together. I'm an absolute beginner and still learning.

Of course there are several ways to solve this problem.

Instead of chaining (eg data.withKey('cheap').withBrand('Levis') - which requires a new class with chainable methods on it) I would go with a recursive method that takes one filterObject. Every key: value pair is a filter:

methods: {
  filter(data, filters) {
    // filters should be an object of filterOptions, e.g. { name: 'blue', weight: 20 }
    const filterProp = Object.keys(filters)[0]; // get first prop to filter for

    // filter your data by this prop and the corresponding value
    const filteredData = data.filter((entry) => {
      return entry[filterProp] === filters[filterProp]
    });

    // get all the other filters through dynamic destructuring
    const { [filterProp]: deletedFilter, ...otherFilters } = filters;

    // if there are no other filters return filteredData,
    // else filter filteredData again with the remaining filters
    return Object.keys(otherFilters).length <= 0
      ? filteredData : this.filter(filteredData, otherFilters);
  },
    ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM