Skip to content

Commit

Permalink
Rustify the fuzzy search
Browse files Browse the repository at this point in the history
The previous version used a bunch of manual string splitting and
recursion and bad decisions.

Recursion - To my knowledge, Rust doesn't support tail call
optimization, so recursion can eventually blow the stack on long
strings.

rust-lang/rust#217

String Splitting - Given that Rust strings are UTF8, there's a non-zero
chance that the algorithm may split on a non-character boundary if the
code isn't careful. Development while creating the split was
problematic at best and resulted in lots of issues involving the
boundary.

Bad decisions - I originally wrote the code in a way that bent Rust to
my will rather than using what Rust provided.
  • Loading branch information
telkkar committed Dec 5, 2016
1 parent 83c561a commit 2f16e78
Showing 1 changed file with 14 additions and 42 deletions.
56 changes: 14 additions & 42 deletions fuzzy_search/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,54 +26,26 @@
/// assert_eq!(fuzzy_search_match("abc", "abcdefg"), true);
/// ```
pub fn fuzzy_search_match(search_string: &str, reference_string: &str) -> bool {
recursive_fuzzy_search(search_string, reference_string)
fuzzy_search(reference_string, search_string)
}

fn recursive_fuzzy_search(search_string: &str, reference_string: &str) -> bool {
let search_len: usize = search_string.len();
let reference_len: usize = reference_string.len();

if search_string == "" {
return true;
}

if reference_string == "" {
return false;
}

// Search strings longer than the reference strings are not valid
if reference_len < search_len {
return false;
}

for (search_index, search_value) in search_string.char_indices() {
// Case where all chars in search string are found
if search_index == search_len {
return true;
}

for (reference_index, reference_value) in reference_string.char_indices() {
if search_value == reference_value {
let (_, rhs_reference_substring) = reference_string.split_at(find_next_char_boundary(reference_string, reference_index));
let (_, rhs_search_substring) = search_string.split_at(find_next_char_boundary(search_string, search_index));
return recursive_fuzzy_search(rhs_search_substring, rhs_reference_substring);
fn fuzzy_search(reference_string: &str, search_string: &str) -> bool {
let mut search_iterator = search_string.chars();
let mut search = search_iterator.next();

for ref_char in reference_string.chars() {
match search {
Some(search_char) => {
if search_char == ref_char {
search = search_iterator.next();
continue;
}
}
}

return false;
}

false
}

fn find_next_char_boundary(string: &str, index: usize) -> usize {
for offset in 1..string.len() + 1 {
if string.is_char_boundary(index + offset) {
return index + offset;
None => return true
}
}

index
search == None
}


Expand Down

0 comments on commit 2f16e78

Please sign in to comment.