Home > OS >  Filter predicate that filters all items after it's encountered a number
Filter predicate that filters all items after it's encountered a number

Time:09-16

Below I have an array filter predicate that will remove all items when it encounters a number, including the number. I'm worried about the performance of this predicate as it runs the entire filter many more times then it needs to (forgive me I don't know the bigO). This is because if I want the global state of when it's encountered the number within the predicate I have to access the third argument which is the entire array.

Is there another way to do this, and still have a predicate with no variables outside the predicate scope?

const filterNumberOrAfter = (_: any, index: number, array: any[]): boolean => {
  let encounterdNumber = false
  const total = array.filter((path) => {
    if (encounterdNumber) return false
    if (typeof path === 'number') {
      encounterdNumber = true
      return false
    }
    return true
  })
  return Boolean(total[index])
}

console.log(['hello', 'world', 'meow', 2, 'example', 'rest'].filter(filterNumberOrAfter))
// [ "hello", "world", "meow" ]

CodePudding user response:

One way to optimize is by encapsulating the predicate within a function and caching the initial run of the filter in the parent scope that way each iteration of the filter has access to the original filtered array that only ran once.

const filterNumberOrAfter = () => {
  let total: string[] = []
  return (_: any, index: number, array: any[]): boolean => {
    if (index === 0) {
      let encounterdNumber = false
      total = array.filter((path) => {
        if (encounterdNumber) return false
        if (typeof path === 'number') {
          encounterdNumber = true
          return false
        }
        return true
      })
    }
    return Boolean(total[index])
  }
}

console.log(['hello', 'world', 'meow', 2, 'example', 'rest'].filter(filterNumberOrAfter()))

CodePudding user response:

The the commenters credit, this is a nice oneliner that is much easier to read.

const getItemsTillNumber = (arr: any[]) => {
  return arr.slice(0, arr.findIndex((item) => typeof item === 'number') || arr.length)
}
  • Related