1+ export const levenshteinDistance = ( str1 , str2 ) => {
2+ const s1 = str1 . toLowerCase ( ) ;
3+ const s2 = str2 . toLowerCase ( ) ;
4+
5+ const track = Array ( s2 . length + 1 ) . fill ( null ) . map ( ( ) => Array ( s1 . length + 1 ) . fill ( 0 ) ) ;
6+
7+ for ( let i = 0 ; i <= s1 . length ; i ++ ) {
8+ track [ 0 ] [ i ] = i ;
9+ }
10+
11+ for ( let j = 0 ; j <= s2 . length ; j ++ ) {
12+ track [ j ] [ 0 ] = j ;
13+ }
14+
15+ for ( let j = 1 ; j <= s2 . length ; j ++ ) {
16+ for ( let i = 1 ; i <= s1 . length ; i ++ ) {
17+ const indicator = s1 [ i - 1 ] === s2 [ j - 1 ] ?0 : 1 ;
18+ track [ j ] [ i ] = Math . min (
19+ track [ j ] [ i - 1 ] + 1 ,
20+ track [ j - 1 ] [ i ] + 1 ,
21+ track [ j - 1 ] [ i - 1 ] + indicator ,
22+ )
23+ }
24+ }
25+ return track [ s2 . length ] [ s1 . length ] ;
26+ } ;
27+
28+ export const calculateSimilarity = ( str1 , str2 ) => {
29+
30+ if ( ! str1 || ! str2 ) {
31+ return 0 ;
32+ }
33+
34+ const distance = levenshteinDistance ( str1 , str2 ) ;
35+ const maxLength = Math . max ( str1 . length , str2 . length ) ;
36+
37+ return 1 - distance / maxLength ;
38+ } ;
39+
40+ export const fuzzySearch = ( input , searchText , threshold = 0.6 ) => {
41+
42+ if ( ! searchText || ! searchText . trim ( ) ) {
43+ return true ;
44+ }
45+
46+ if ( ! input ) {
47+ return false ;
48+ }
49+
50+ const trimmedSearch = searchText . trim ( ) . toLowerCase ( ) ;
51+ const inputLower = input . toLowerCase ( ) ;
52+
53+ if ( inputLower . includes ( trimmedSearch ) ) {
54+ return true ;
55+ }
56+
57+ if ( trimmedSearch . length < 2 ) {
58+ return false ;
59+ }
60+
61+ const similarity = calculateSimilarity ( input , searchText ) ;
62+
63+ if ( similarity >= threshold ) {
64+ return true ;
65+ }
66+
67+ const searchWords = trimmedSearch . split ( / \s + / ) ;
68+ const inputWords = inputLower . split ( / \s + / ) ;
69+
70+ return searchWords . every ( searchWord => {
71+ if ( searchWord . length < 2 ) {
72+ return true ;
73+ }
74+ return inputWords . some ( inputWord => {
75+
76+ if ( inputWord . startsWith ( searchWord ) ) {
77+ return true ;
78+ }
79+
80+ const wordSimilarity = calculateSimilarity ( inputWord , searchWord ) ;
81+ return wordSimilarity >= threshold ;
82+ } ) ;
83+ } ) ;
84+ } ;
0 commit comments