Making the Filter
Tags: tutorial, javascript, beginners, programming
Published: 2021-11-01 02:15:00

Picking up from where we were in the [Parser](https://dev.to/noriller/making-the-parser-32lp):

```jsx
MyBasicParser(
  `some random string something "quoted here" not here 'here again' tag:value something alone: and other:tag :value`
);

// it returns:
/* 
	{
	  singleValues:  [ 'some','random','string','something','not','here','something','alone:','and',':value' ],
	  quotedValues: [ 'quoted here', 'here again' ],
	  tagValues: [['tag', 'value'], ['other', 'tag']]
	}
*/
```

## Now... how do we use it?

Here's a draft of what we need:

```jsx
function MyBasicFilter(arrayToBeFiltered) {
	function doFilter(parsedObject) {
		return arrayToBeFiltered.filter(
			(item) => FilterMagic({ item, parsedObject })
		);
	}
	
	function FilterMagic({ item, parsedObject }){'???'}

	return {
		filter: (parsedObject) => doFilter(parsedObject)
	};
}

// To use this:
const myArray = [/* ... values ... */];
const basicFilter = MyBasicFilter(myArray);

const parsedSearch = MyBasicParser(/* that big string */);
const filterResult = basicFilter.filter(parsedSearch);
```

Here we will use a closure, just so we can prepare the function and then just call it afterwards.

### Filter Magic

For that we will be needing:

```jsx
function FilterMagic({
  item,
  parsedObject,
}) {
  // check the single values
  // check the quoted values
  // check the tag values
  return boolean;
}
```

While writing this, I've made it in a way I didn't even though about using in [EasyFilter](https://www.npmjs.com/package/@noriller/easy-filter)!

```jsx
function FilterMagic({ item, parsedObject }) {
  // this concatenates all strings in the item
  const stringValue = Object.values(item).join(' ');

  // using an object we avoid having to use a switch statement
  // the code is more clear and easier to read
  // and should we need to add more filters we can add them here in a simple way
  const myMagicFunctions = {
    // this is basically the "base case", it will check if the baseString have the values we are looking for with Regex using the case insensitive flag
    // we pass the stringValue of the item as default, but doing this allows other functions to override it
    singleValues: (string, baseString = stringValue) => Boolean(baseString.match(RegExp(string, 'i'))),
    // for the quoted values, we split them at the space and then call the sibling function "singleValues" for each value
    // and by using the "every" function we check if all the substrings are found
    // we could also had just called the "singleValues" function without splitting the string
    // but that would mean the it would check if it matched the exact string in order
    // it would look like this:
    // quotedValues: (string) => myMagicFunctions.singleValues(string),
    quotedValues: (string) => string.split(' ').every((subString) => myMagicFunctions.singleValues(subString)),
    // finally, the tags we spread the tag/value and override the default baseString of "singleValues" with the value of the tag
    tagValues: ([tag, value]) => myMagicFunctions.singleValues(value, item[tag]),
  }

  // we break down the parsedObject and with "some" check if any of the single, quoted or tag values have any match
  return Object.entries(parsedObject).some(
    ([parsedType, values]) => {
      // since each can hold an array, we loop through them using "some"
      // also, by using "some", it already stops in the first match!
      return values.some((payload) =>
        // and if this isn't magic, I don't know what is!
        // we use the types coming from the parsedObject,
        // if there's a match, we call the function that matches the type
        // and pass the payload (that can be either a string or a tuple)
        // if there's no match, it will return false by default
        myMagicFunctions[parsedType]?.(payload) ?? false
      );
    })
}

// If you want to play around with the FilterMagic
// here's a mockItem for you to test
const mockItem = {
  ghosts: "Are spooky?",
  regex: "More spooky?",
  happy: "Halloween"
};
// and here's a mockParsedObject
const mockParsedObject = {
  singleValues: ['spooky', 'spoolk'],
  quotedValues: ['spooky more', 'morr spook'],
  tagValues: [['happy', 'halloween']]
};
// invalidate some of the values to see what's called and what's not
// as is, it will stop at the very first one because "spooky" is in the item!
```

## The Final Result

```jsx
function MyBasicFilter(arrayToBeFiltered) {
  function doFilter(parsedObject) {
    return arrayToBeFiltered.filter(
      (item) => FilterMagic({ item, parsedObject })
    );
  }

  function FilterMagic({ item, parsedObject }) {
    const stringValue = Object.values(item).join(' ');

    const myMagicFunctions = {
      singleValues: (string, baseString = stringValue) => Boolean(baseString.match(RegExp(string, 'i'))),
      quotedValues: (string) => string.split(' ').every((subString) => myMagicFunctions.singleValues(subString)),
      tagValues: ([tag, value]) => myMagicFunctions.singleValues(value, item[tag]),
    };

    return Object.entries(parsedObject).some(
      ([parsedType, values]) => {
        return values.some((payload) =>
          myMagicFunctions[parsedType]?.(payload) ?? false
        );
      });
  }

  return {
    filter: (parsedObject) => doFilter(parsedObject)
  };
}
```

Fortunately, the filter is the easiest part... 
Unfortunately... it's more straight forward code.

I'm happy that I've managed to do something totally different than what I've used in [EasyFilter](https://www.npmjs.com/package/@noriller/easy-filter), but this is a way simpler version of that one... 
Although I actually might think about using what we did here in there!

Hey... how about it? 
Check if YOU can can do it... fork the project and then send a PR!

---

[![buy me a spook coffee](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xkyd8yo1zv3rtysodwxp.png)](https://buymeacoffee.com/noriller)

Cover Photo by [Wade Austin Ellis](https://unsplash.com/@wadeaustinellis?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)