Fuzzy Search Technique
Tags: javascript, searching
Published: 2022-10-14 12:19:16

 Adding one way how we can perform search operation on given data set & find all possible result sets
```js

// If this isMatchingInString function return True means that text exist We can consider that object or string

const dummyDataSet = [
  { titleText: "DischargeSummary" },
  { titleText: "x name" },
  { titleText: "y name" }
];
const filteredData = [];

const getSearchedRecord = (value) => {
  const searchedText = value;
  const recordArray = JSON.parse(JSON.stringify(dummyDataSet));

  const filteredData = recordArray.filter((eachRecord) => {
    if (eachRecord.titleText) {
      const title = eachRecord?.titleText;
      const isTitleMatch = isMatchingInString(searchedText, title);
      if (isTitleMatch) {
        return eachRecord;
      }
    }
  });
  return filteredData;
};

// Main Func call to check if we have search Text in data i.e. SearchIN (consider SearchIN to be string)
const isMatchingInString = (searchText, SearchIN) => {
  return isTextMatchingSync(searchText, SearchIN);
};

const permutator = (inputArr) => {
  const result = [];

  function permute(arr, m = []) {
    if (arr.length === 0) {
      let combination = "";
      m.forEach((eachChar) => {
        combination += eachChar;
      });
      result.push(combination);
    } else {
      for (let i = 0; i < arr.length; i++) {
        const curr = arr.slice();
        const next = curr.splice(i, 1);
        permute(curr.slice(), m.concat(next));
      }
    }
  }

  permute(inputArr);

  return result;
};

// example SearchText = "Di"
const createSearchCombinations = (searchText) => {
  // regex to find Matching
  const regex = /(\w+)[\/\s]([\s\S]*)/m;
  const match = regex.exec(searchText);
  const combinations = [];
  const subsets = [];
  if (match && match.length > 1) {
    for (let i = 1; i < match.length; i++) {
      if (match[i].length) {
        subsets.push(match[i]);
      }
    }
  }
  combinations.push(searchText);

  if (subsets.length) {
    const newSubsets = permutator(subsets);
    newSubsets.forEach((eachNewSubset) => {
      combinations.push(eachNewSubset);
      const specialCharRegex = /[^A-Za-z0-9]/g;
      const searchTextExceptSpecialChar = eachNewSubset.replace(
        specialCharRegex,
        ""
      );
      combinations.push(searchTextExceptSpecialChar);

      const removeConsecutiveDuplicateRegex = /(.)\1+/g;
      const searchTextExceptConsecutiveRepeatingChar = searchTextExceptSpecialChar.replace(
        removeConsecutiveDuplicateRegex,
        "$1"
      );

      combinations.push(searchTextExceptConsecutiveRepeatingChar);

      const removeVowelRegex = /[aeiou]/g;
      const searchTextExceptVowelChar = searchTextExceptConsecutiveRepeatingChar.replace(
        removeVowelRegex,
        ""
      );

      combinations.push(searchTextExceptVowelChar);
    });
  }

  const specialCharRegex = /[^A-Za-z0-9]/g;
  const searchTextExceptSpecialChar = searchText.replace(specialCharRegex, "");
  combinations.push(searchTextExceptSpecialChar);

  const removeConsecutiveDuplicateRegex = /(.)\1+/g;
  const searchTextExceptConsecutiveRepeatingChar = searchTextExceptSpecialChar.replace(
    removeConsecutiveDuplicateRegex,
    "$1"
  );

  combinations.push(searchTextExceptConsecutiveRepeatingChar);

  const removeVowelRegex = /[aeiou]/g;
  const searchTextExceptVowelChar = searchTextExceptConsecutiveRepeatingChar.replace(
    removeVowelRegex,
    ""
  );

  combinations.push(searchTextExceptVowelChar);

  return [...new Set(combinations)];
};
// output of combination FUnction = [
//   "Di ",
//   "Di",
//   "Di",
//   "Di",
//   "D",
//   "Di",
//   "Di"
// ]

const isTextMatchingSync = (searchedText, SearchIN) => {
  // removing extra White Space i.e. avoiding search of " " Empty String
  if (!searchedText.trim()) {
    return true;
  }
  const combinations = createSearchCombinations(searchedText);
  const res = combinations.find((eachCombination) => {
    return fuzzySearch(SearchIN, eachCombination);
  });
  if (res) {
    return true;
  } else {
    return false;
  }
};

// Di--> text, Di --> Combination
const fuzzySearch = (text, eachCombination) => {
  if (!eachCombination.length) {
    return true;
  }
  /*Parameter text is a title, search is the user's search*/
  // remove spaces, lower case the search so the search
  // is case insensitive
  const search = eachCombination.replace(" ", "").toLowerCase();
  const tokens = [];
  let searchPosition = 0;

  // Go through each character in the text
  for (let n = 0; n < text.length; n++) {
    let textChar = text[n];
    // if we match a character in the search, highlight it
    if (
      searchPosition < search.length &&
      textChar.toLowerCase() === search[searchPosition]
    ) {
      textChar = "<b>" + textChar + "</b>";
      searchPosition += 1;
    }
    tokens.push(textChar);
  }
  // If are characters remaining in the search text,
  // return an empty string to indicate no match
  if (searchPosition !== search.length) {
    return false;
  }
  return true;
};

console.log(getSearchedRecord("x"));


```