DEV Community

ZeeshanAli-0704
ZeeshanAli-0704

Posted on

Fuzzy Search Technique

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


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


Enter fullscreen mode Exit fullscreen mode

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay