필터 만들기

우리가 있었던 곳에서 픽업:

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']]
    }
*/


자... 어떻게 사용할까요?



필요한 초안은 다음과 같습니다.

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


여기서 우리는 함수를 준비하고 나중에 호출할 수 있도록 클로저를 사용할 것입니다.

필터 매직



이를 위해서는 다음이 필요합니다.

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


이 글을 쓰면서 in EasyFilter 에 써도 안 되는 방법으로 만들어 봤습니다!

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!


최종 결과




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


다행히도 필터가 가장 쉬운 부분입니다...
불행히도 ... 더 간단한 코드입니다.

EasyFilter에서 사용한 것과는 완전히 다른 작업을 수행할 수 있어서 기쁩니다. 하지만 이것은 훨씬 더 간단한 버전입니다...
실제로 우리가 여기에서 한 것을 사용하는 것에 대해 생각할 수도 있지만!

이봐... 어때?
할 수 있는지 확인하세요... 프로젝트를 포크한 다음 PR을 보내세요!




표지 사진 작성자: Wade Austin Ellis on Unsplash

좋은 웹페이지 즐겨찾기