0

I'm using Vue and trying to filter an array of results using a JS function composition.

My Vue computed values are like so, but can't get filteredByAll to accept a third option getByThing. Right now the filterByAll just filters on the category and keyword search.

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)
      },
      filteredByThing() {
        return getByThing(this.list, this.thing)
      }
    }

My standard JS functions

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

function getByThing(list, thing) {
  if (!thing) return list
  return list.filter(item => item.thing === thing)
}

I'm trying to wrap my head around the functional stuff but struggling from what I've read.

2 Answers 2

2

This should do it:

filteredByAll() {
    return getByThing(getByCategory(getByKeyword(this.list, this.keyword), this.category), this.thing)
},
Sign up to request clarification or add additional context in comments.

3 Comments

ah, because it goes from inner most to outer most, right?
Yes, each function returns a list, so you can simply plug the result from one function as list parameter into the next. The order is only relevant in so far as one can optimize the speed by filtering first by whatever yields the lowest number of results.
Thanks Chris - I think I get it and where I was going wrong before. I think I was trying it the other way.
0

When we rewrite the functions to a curried version and the last argument is the list we can compose them like:

const trippleFilter = (keyword, category, thing) => pipe (
    getByKeyword (keyword),
    getByCategory (category),
    getByThing (thing)
)

Working Code

const pipe = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)))

const getByKeyword = keyword => list => {
    const search = keyword.trim()
    return !search.length
        ? list
        : list.filter(item => item.name.indexOf(search) > -1)
}
  
const getByCategory = category => list =>
    !category
        ? list
        : list.filter(item => item.category === category)
  
const getByThing = thing => list =>
    !thing
        ? list
        : list.filter(item => item.thing === thing)

const trippleFilter = (keyword, category, thing) => pipe (
    getByKeyword (keyword),
    getByCategory (category),
    getByThing (thing)
)

const x = [
    {
        name: 'pizza',
        category: 'fastfood',
        thing: 'pizza salami'
    },
    {
        name: 'burger',
        category: 'fastfood',
        thing: 'hamburger'
    }
]

console.log(trippleFilter ('pizza', 'fastfood', 'pizza salami') (x))

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.