Implement Fuzzy Search in Syncfusion WinUI AutoComplete
Tags: winui, development, ui, autocomplete
Published: 2023-02-21 13:56:05

---
title: Implement Fuzzy Search in Syncfusion WinUI AutoComplete
published: true
date: 2023-02-21 11:00:00 UTC
tags: winui, development, ui, autocomplete
canonical_url: https://www.syncfusion.com/blogs/post/fuzzy-search-in-winui-autocomplete.aspx
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qb3fd5b6h2uqsiatx62w.png
---
A fuzzy search is a technique that matches string approximately and returns a list of results even though spellings may not match exactly. A fuzzy matching algorithm can help ignore typo errors or when the exact word is unknown. This technique is commonly used in search engines like Bing and Google.

There are many algorithms available to implement a fuzzy search. In this blog, we will discuss one of them, Levenshtein distance.

## What is Levenshtein distance?

Levenshtein distance is the favored approach for finding the edit distance, which is the number of character changes needed to convert the search word to the exact phrase. The following single-character changes are used to compute edit distance.

- **Insertion:**  Syncfuson → Syncfus **i** on
- **Deletion:**  Syncfus **s** ion → Syncfusion
- **Substitution:**  Syncfus **e** on → Syncfus **i** on

In all these cases, the distance is 1. Let us see another example in which the distance is more than 1.

Let us take Syncfussen as the search word. To convert this to Syncfusion, we must make three changes.

- Deletion: Syncfus **s** en -> Syncfusen
- Insertion: Syncfusen-> Syncfus **i** en
- Substitution: Syncfusi **e** n-> Syncfusi **o** n

### The distance matrix

The previously discussed examples are straightforward. In a real-world scenario, the search and the exact words may be pretty complex, and we must write generic logic to find the distance between them. There are many references online regarding this. In this blog, we will look at it briefly.

Let’s take the search and actual words as **DESTP** and **DESKTOP** , respectively. The initial table will look like the following one. We will have an additional index from their original length in both rows and columns. You will see why when you understand how this table works. The populated cells are just indices. Also, ignore the empty cells in the top left. We will not need them.

<table>
<tbody>
<tr style="background: none;">
<td style="width: 65px;" width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>D</p>
</td>
<td width="64">
<p>E</p>
</td>
<td width="64">
<p>S</p>
</td>
<td width="64">
<p>K</p>
</td>
<td width="64">
<p>T</p>
</td>
<td width="64">
<p>O</p>
</td>
<td width="48">
<p>P</p>
</td>
</tr>
<tr>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>0</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="64">
<p>3</p>
</td>
<td width="64">
<p>4</p>
</td>
<td width="64">
<p>5</p>
</td>
<td width="64">
<p>6</p>
</td>
<td width="48">
<p>7</p>
</td>
</tr>
<tr>
<td width="64">
<p>D</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="48">
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td width="64">
<p>E</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="48">
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td width="64">
<p>S</p>
</td>
<td width="64">
<p>3</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="48">
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td width="64">
<p>T</p>
</td>
<td width="64">
<p>4</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="48">
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td width="64">
<p>P</p>
</td>
<td width="64">
<p>5</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="48">
<p>&nbsp;</p>
</td>
</tr>
</tbody>
</table>
We will start filling the 2 \* 2 matrix.
<table>
<tbody>
<tr style="background: none;">
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="48">
<p>D</p>
</td>
</tr>
<tr>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>0</p>
</td>
<td width="48">
<p>1</p>
</td>
</tr>
<tr>
<td width="64">
<p>D</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="48">
<p>&nbsp;</p>
</td>
</tr>
</tbody>
</table>
The value of the empty cell will be calculated based on the following scenarios:

- Minimum of three other cells if the characters match.
- Minimum of three other cells + 1 if the characters do not match.

Here, the characters match. Hence the empty cell value for the D vs. D is Min(0, 1, 1), i.e., 0.
<table>
<tbody>
<tr style="background: none;">
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="48">
<p>D</p>
</td>
</tr>
<tr>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>0</p>
</td>
<td width="48">
<p>1</p>
</td>
</tr>
<tr>
<td width="64">
<p>D</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="48">
<p>0</p>
</td>
</tr>
</tbody>
</table>
The table will look like the following one.
<table style="width: 100%;">
<tbody>
<tr style="background: none;">
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>D</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>E</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>S</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>K</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>T</p>
</td>
<td style="width: 8.45238%;" width="64">
<p>O</p>
</td>
<td style="width: 11.3095%;" width="48">
<p>P</p>
</td>
</tr>
<tr>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>0</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>1</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>2</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>3</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>4</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>5</p>
</td>
<td style="width: 8.45238%;" width="64">
<p>6</p>
</td>
<td style="width: 11.3095%;" width="48">
<p>7</p>
</td>
</tr>
<tr>
<td style="width: 11.1905%;" width="64">
<p>D</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>1</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>0</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 8.45238%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.3095%;" width="48">
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td style="width: 11.1905%;" width="64">
<p>E</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>2</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 8.45238%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.3095%;" width="48">
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td style="width: 11.1905%;" width="64">
<p>S</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>3</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 8.45238%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.3095%;" width="48">
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td style="width: 11.1905%;" width="64">
<p>T</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>4</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 8.45238%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.3095%;" width="48">
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td style="width: 11.1905%;" width="64">
<p>P</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>5</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.1905%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 8.45238%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.3095%;" width="48">
<p>&nbsp;</p>
</td>
</tr>
</tbody>
</table>
We will move to the following 2 \* 2 matrix, the 2 \* 2 matrix for D vs. E.
<table style="width: 100%;">
<tbody>
<tr style="background: none;">
<td style="width: 45.9318%;" width="64">
<p>1</p>
</td>
<td style="width: 53.1496%;" width="53">
<p>2</p>
</td>
</tr>
<tr>
<td style="width: 45.9318%;" width="64">
<p>0</p>
</td>
<td style="width: 53.1496%;" width="53">
<p>&nbsp;</p>
</td>
</tr>
</tbody>
</table>
Here, the characters do not match. Hence, the empty cell value for the D vs. E is Min(1, 2, 0) + 1, i.e., 1.

The table will look like the following one.
<table style="width: 100%;">
<tbody>
<tr style="background: none;">
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>D</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>E</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>S</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>K</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>T</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>O</p>
</td>
<td style="width: 8.45238%;" width="48">
<p>P</p>
</td>
</tr>
<tr>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>0</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>1</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>2</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>3</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>4</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>5</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>6</p>
</td>
<td style="width: 8.45238%;" width="48">
<p>7</p>
</td>
</tr>
<tr>
<td style="width: 11.0714%;" width="64">
<p>D</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>1</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>0</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>1</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 8.45238%;" width="48">
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td style="width: 11.0714%;" width="64">
<p>E</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>2</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 8.45238%;" width="48">
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td style="width: 11.0714%;" width="64">
<p>S</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>3</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 8.45238%;" width="48">
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td style="width: 11.0714%;" width="64">
<p>T</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>4</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 8.45238%;" width="48">
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td style="width: 11.0714%;" width="64">
<p>P</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>5</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 11.0714%;" width="64">
<p>&nbsp;</p>
</td>
<td style="width: 8.45238%;" width="48">
<p>&nbsp;</p>
</td>
</tr>
</tbody>
</table>

If you follow this for the whole table, the final table will look like the following one.
<table>
<tbody>
<tr style="background: none;">
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>D</p>
</td>
<td width="64">
<p>E</p>
</td>
<td width="64">
<p>S</p>
</td>
<td width="64">
<p>K</p>
</td>
<td width="64">
<p>T</p>
</td>
<td width="64">
<p>O</p>
</td>
<td width="48">
<p>P</p>
</td>
</tr>
<tr>
<td width="64">
<p>&nbsp;</p>
</td>
<td width="64">
<p>0</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="64">
<p>3</p>
</td>
<td width="64">
<p>4</p>
</td>
<td width="64">
<p>5</p>
</td>
<td width="64">
<p>6</p>
</td>
<td width="48">
<p>7</p>
</td>
</tr>
<tr>
<td width="64">
<p>D</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="64">
<p>0</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="64">
<p>3</p>
</td>
<td width="64">
<p>4</p>
</td>
<td width="64">
<p>5</p>
</td>
<td width="48">
<p>6</p>
</td>
</tr>
<tr>
<td width="64">
<p>E</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="64">
<p>0</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="64">
<p>3</p>
</td>
<td width="64">
<p>4</p>
</td>
<td width="48">
<p>5</p>
</td>
</tr>
<tr>
<td width="64">
<p>S</p>
</td>
<td width="64">
<p>3</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="64">
<p>0</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="64">
<p>3</p>
</td>
<td width="48">
<p>4</p>
</td>
</tr>
<tr>
<td width="64">
<p>T</p>
</td>
<td width="64">
<p>4</p>
</td>
<td width="64">
<p>3</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="64">
<p>1</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="48">
<p>3</p>
</td>
</tr>
<tr>
<td width="64">
<p>P</p>
</td>
<td width="64">
<p>5</p>
</td>
<td width="64">
<p>4</p>
</td>
<td width="64">
<p>3</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="64">
<p>2</p>
</td>
<td width="48">
<p>2</p>
</td>
</tr>
</tbody>
</table>

The cell’s value at the bottom right is the distance between DESTP and DESKTOP. The value is 2. To convert DESTP to DESKTOP, we must make two changes. This approach can be used for calculating the distance between any two words.

Let’s convert this into **C#** logic.

### Implementing distance matrix in C#

You can find the comment for each line. This is the logic we just discussed.

```csharp
public int LevenshteinDistance(string searchWord, string actualWord)
{
  var searchWordLength = searchWord.Length;
  var actualWordLength = actualWord.Length;
  
  //Forming a table that has a length one higher in both rows and columns.
  var matrix = new int[searchWordLength + 1, actualWordLength + 1];

  if (searchWordLength == 0)
     return actualWordLength;

  if (actualWordLength == 0)
     return searchWordLength;

  //Initializing with indices.
  for (var i = 0; i <= searchWordLength; matrix[i, 0] = i++) { }
  for (var j = 0; j <= actualWordLength; matrix[0, j] = j++) { }

  for (var i = 1; i <= searchWordLength; i++)
  {
    for (var j = 1; j <= actualWordLength; j++)
    {
       //If the characters do not match, we will add 1.
       var cost = (actualWord[j - 1] == searchWord[i - 1]) ? 0 : 1;

       //Minimum of the 3 cells + above cost.
       matrix[i, j] = Math.Min(
       Math.Min(matrix[i - 1, j] + 1, matrix[i, j - 1] + 1),
       matrix[i - 1, j - 1] + cost);
     }
  }
  // Return the value at the right bottom.
  return matrix[searchWordLength, actualWordLength];
}
```

## Integration with Syncfusion WinUI AutoComplete

Let’s see how to integrate this method with the Syncfusion [WinUI AutoComplete](https://www.syncfusion.com/winui-controls/autocomplete "Syncfusion WinUI AutoComplete") control. We are not going to see in detail how to do custom filtering in AutoComplete. There are already [user guides](https://help.syncfusion.com/winui/autocomplete/searching-filtering#custom-filtering "Custom filtering in Syncfusion WinUI AutoComplete") and a [blog](https://www.syncfusion.com/blogs/post/achieve-google-like-autosuggestions-with-the-winui-autocomplete-control.aspx "Blog: Achieve Google-Like autosuggestions with the WinUI AutoComplete Control") for this.

Following is the completed code snippet. We have included the previously mentioned **LevenshteinDistance** method in this class. Other methodologies and logic is self-explanatory. We have also added comments in the required lines for better understanding.

**XAML:**

```xml
<editors:SfAutoComplete
                Width="200"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                PlaceholderText="Select the social media"
                ItemsSource="{Binding SocialMedias}">
 <editors:SfAutoComplete.FilterBehavior>
   <local:CustomFiltering/>
 </editors:SfAutoComplete.FilterBehavior>
</editors:SfAutoComplete>
```

**C#:**

```csharp
namespace FuzzySearching
{
  public class CustomFiltering : IAutoCompleteFilterBehavior
  {
    public Task<object> GetMatchingItemsAsync(SfAutoComplete source, AutoCompleteFilterInfo filterInfo)
    {
      //To include the results that match the search word.
      List<string> builtInResult = (source.ItemsSource as 
List<string>).Where(stringToCheck => stringToCheck.ToLower().Contains(filterInfo.Text.ToLower())).ToList();

      //Results found through the new fuzzy search logic. To allow words with more differences, you can decrease the value.
      List<string> fuzzyResult = FuzzySearch(filterInfo.Text, source.ItemsSource as List<string>, 0.4);

      //Combining both the results and returning it.
      IEnumerable<string> combinedResult = builtInResult.Union(fuzzyResult);
      return Task.FromResult((object)combinedResult);
    }

    public List<string> FuzzySearch(string searchWord, List<string> actualWords, double requiredMatchingFactor)
    {
      List<string> foundWords = new List<string>();
   
      foreach (string s in actualWords)
      {
        // Calculate the Levenshtein-distance.
        int levenshteinDistance =
LevenshteinDistance(s, searchWord);

        // Length of the longer string.
        int length = Math.Max(searchWord.Length, s.Length);

        // Calculate the score and convert to the matching factor.
        double matchingFactor = 1.0 - (double)levenshteinDistance / length;

        //If the matching factor is higher than the required matching factor, we will include that word.
        //The lower the required matching factor, the more difference between the words will be allowed.
        if (matchingFactor > requiredMatchingFactor)
            foundWords.Add(s);
     }
     return foundWords;
   }
   
   public int LevenshteinDistance(string searchWord, string actualWord)
   {
      var searchWordLength = searchWord.Length;
      var actualWordLength = actualWord.Length;
  
      //Forming a table that has a length one higher in both rows and columns.
      var matrix = new int[searchWordLength + 1, actualWordLength + 1];

      if (searchWordLength == 0)
         return actualWordLength;

      if (actualWordLength == 0)
         return searchWordLength;

      //Initializing with indices.
      for (var i = 0; i <= searchWordLength; matrix[i, 0] = i++) { }
      for (var j = 0; j <= actualWordLength; matrix[0, j] = j++) { }

      for (var i = 1; i <= searchWordLength; i++)
      {
        for (var j = 1; j <= actualWordLength; j++)
        {
           //If the characters do not match, we will add 1.
           var cost = (actualWord[j - 1] == searchWord[i - 1]) ? 0 : 1;

          //Minimum of the 3 cells + above cost.
          matrix[i, j] = Math.Min(
            Math.Min(matrix[i - 1, j] + 1, matrix[i, j - 1] + 1),
            matrix[i - 1, j - 1] + cost);
        }
      }
      // Return the value at the bottom right. 
      return matrix[searchWordLength, actualWordLength];
    }
  }

  public sealed partial class MainWindow : Window
  {
    public MainWindow()
    {
       this.InitializeComponent();
    }
  }

  public class SocialMediaViewModel
  {
    public List<string> SocialMedias { get; set; }
    public SocialMediaViewModel()
    {
      this.SocialMedias = new List<string>();
      this.SocialMedias.Add("Facebook");
      this.SocialMedias.Add("Twitter");
      this.SocialMedias.Add("Google Plus");
      this.SocialMedias.Add("Instagram");
      this.SocialMedias.Add("LinkedIn");
      this.SocialMedias.Add("Skype");
      this.SocialMedias.Add("Telegram");
      this.SocialMedias.Add("Televzr");
      this.SocialMedias.Add("Tik Tok");
      this.SocialMedias.Add("Tout");
      this.SocialMedias.Add("Tumblr");
      this.SocialMedias.Add("Twitter");
      this.SocialMedias.Add("Vimeo");
      this.SocialMedias.Add("WhatsApp");
      this.SocialMedias.Add("YouTube");
    }
  }
}
```

### With fuzzy search
<figure>

  <img src="https://www.syncfusion.com/blogs/wp-content/uploads/2023/02/With-Fuzzy-Search.jpg" alt="With Fuzzy Search" style="width:100%">

  <figcaption>With Fuzzy Search</figcaption>

</figure>
### Without fuzzy search

We would not have the search results if we did not use our fuzzy search algorithm.
<figure>

  <img src="https://www.syncfusion.com/blogs/wp-content/uploads/2023/02/Without-Fuzzy-Search.jpg" alt="Without Fuzzy Search" style="width:100%">

  <figcaption>Without Fuzzy Search</figcaption>

</figure>
## GitHub reference

Also, you can find the complete demo for [Implementing Fuzzy Search in WinUI AutoComplete on GitHub](https://github.com/SyncfusionExamples/ej2-fuzzy-search-autocomplete/ "Fuzzy Searching with WinUI AutoComplete GitHub demo").

## Conclusion

In this blog, we have seen how to calculate Levenshtein distance and use it for fuzzy searching. We have also seen how to integrate this in the Syncfusion [WinUI AutoComplete](https://www.syncfusion.com/winui-controls/autocomplete "Syncfusion WinUI AutoComplete") control.

If you have any questions about this blog, please let us know in the comments. If you have any issues or require new features, contact us through our [support forum](https://www.syncfusion.com/forums "Syncfusion Support Forum"), [support portal](https://support.syncfusion.com/ "Syncfusion Support Portal"), or [feedback portal](https://www.syncfusion.com/feedback "Syncfusion Feedback Portal"). We are always happy to assist you!

## Related links

- [Advantages of Using Syncfusion WinUI Controls over Framework Controls: Part 2](https://www.syncfusion.com/blogs/post/advantages-of-using-syncfusion-winui-controls-over-framework-controls-part-2.aspx "Blog: Advantages of Using Syncfusion WinUI Controls over Framework Controls: Part 2")
- [Design a Temperature Monitor like a Pro Using WinUI Radial Gauge](https://www.syncfusion.com/blogs/post/temperature-monitor-winui-radial-gauge.aspx "Blog: Design a Temperature Monitor like a Pro Using WinUI Radial Gauge")
- [Easily Design a Sleep Tracker Using WinUI Radial Gauge](https://www.syncfusion.com/blogs/post/design-a-sleep-tracker-using-winui-radial-gauge.aspx "Blog: Easily Design a Sleep Tracker Using WinUI Radial Gauge")
- [Syncfusion Mobile and Desktop Controls Are Now Compatible with .NET 7](https://www.syncfusion.com/blogs/post/syncfusion-mobile-and-desktop-controls-are-now-compatible-with-net-7.aspx "Blog: Syncfusion Mobile and Desktop Controls Are Now Compatible with .NET 7")