ā† Writing

Two Dimensional Array Filtering with RegExp

Updated 5 months ago

Another thorny problem. I have an array of categories. Actually they're the transaction categories from Plaid's API. Six hundred and two to be exact.

The problem I was solving for was how to filter the inner array with regex performantly for a search suggest to recategorize transactions.

The data is organized in my app in a two dimensional array shaped like this:

[
   { hierarchy: ["Food and Drink"] },
   { hierarchy: ["Food and Drink", "Restaurants"] },
   { hierarchy: ["Food and Drink", "Restaurants", "Turkish"] },
   ... and so forth
]

Note that the inner array has varying lengths and repeats many of the same strings.

We're going to to use Array.filter and RegExp to hit the array. First we need to get down to the second array.

 const allCats = Categories.find().fetch()
 let results = allCats.filter((category) => {
    let matchSub = category.hierarchy.filter((subCategory) => {
    	return true;
    })
 })

When you return true in Array.filter, it will return the category so thus far we'll return every subCategory. In the second level we need to perform our RegExp.

Now I'm pretty lazy when I'm using applications I make, so I tend to put in a lot of conveniences. I can't be bothered to type the whole category name or use capitalization so let's add the flags "i" to the expression. That makes it match using case insensitive logic. We'll also throw a "^" at the beginning so we match the first part of the subcategory.

 const allCats = Categories.find().fetch()
 let results = allCats.filter((category) => {
   let matchSub = category.hierarchy.filter((subCategory) => {
      const regex = new RegExp('^' + query, 'i')
        return regex.test(subCategory)
      })
   console.log(matchSub)
   return true
 })

Let's see where we're at. This should start sending back matches. If the subCategory matches then it will return an array with that match in it. Otherwise it will be an empty array.

All we need to do is return the matchSub if it's length is greater than 0, otherwise we'll return.

Final solution

 const allCats = Categories.find().fetch()
 let results = allCats.filter((category) => {
   let matchSub = category.hierarchy.filter((subCategory) => {
      const regex = new RegExp('^' + query, 'i')
        return regex.test(subCategory)
      })
   if (matchSub.length > 0) {
     return matchSub
   }
   return
 })

Finding this useful?

You can get these articles in your inbox, plus updates about projects I'm working on. I won't send you any spam and you can unsubscribe at any time.

A small favor

Was anything I wrote confusing, outdated, or incorrect? Please let me know! Just write a few words below and Iā€™ll be sure to amend this post with your suggestions.