Skip to content

Commit 3406c76

Browse files
authored
Simplify Affix::find (#24)
* Rewrite Affix::find to be much simpler * Rename Affix::find parameters to not be string * Remove unused `LevMatchingBlock` struct * Make `Affix` type simpler
1 parent 6afc535 commit 3406c76

File tree

1 file changed

+23
-78
lines changed

1 file changed

+23
-78
lines changed

src/editops.rs

Lines changed: 23 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -40,25 +40,18 @@ pub struct LevEditOp {
4040
pub second_start: usize, /* destination position */
4141
}
4242

43-
#[derive(Debug, PartialEq, Eq)]
44-
pub struct LevMatchingBlock {
45-
pub first_start: usize,
46-
pub second_start: usize,
47-
pub len: usize,
48-
}
49-
5043
pub fn editops_find<T>(query: &[T], choice: &[T]) -> Vec<LevEditOp>
5144
where T: PartialEq {
52-
let string_affix = Affix::find(query, choice);
45+
let Affix {
46+
prefix_len,
47+
suffix_len,
48+
} = Affix::find(query, choice);
5349

54-
let first_string_len = string_affix.first_string_len;
55-
let second_string_len = string_affix.second_string_len;
56-
let prefix_len = string_affix.prefix_len;
57-
let first_string = &query[prefix_len..prefix_len + first_string_len];
58-
let second_string = &choice[prefix_len..prefix_len + second_string_len];
50+
let first_string = &query[prefix_len..query.len() - suffix_len];
51+
let second_string = &choice[prefix_len..choice.len() - suffix_len];
5952

60-
let matrix_columns = first_string_len + 1;
61-
let matrix_rows = second_string_len + 1;
53+
let matrix_columns = first_string.len() + 1;
54+
let matrix_rows = second_string.len() + 1;
6255

6356
// TODO maybe use an actual matrix for readability
6457
let mut cache_matrix: Vec<usize> = vec![0; matrix_rows * matrix_columns];
@@ -186,73 +179,25 @@ where
186179

187180
pub struct Affix {
188181
pub prefix_len: usize,
189-
pub first_string_len: usize,
190-
pub second_string_len: usize,
182+
pub suffix_len: usize,
191183
}
192184

193185
impl Affix {
194-
pub fn find<T>(first_string: &[T], second_string: &[T]) -> Affix
186+
pub fn find<T>(s1: &[T], s2: &[T]) -> Affix
195187
where T: PartialEq {
196-
// remove common prefix and suffix (linear vs square runtime for levensthein)
197-
let mut first_iter = first_string.iter();
198-
let mut second_iter = second_string.iter();
199-
200-
let mut limit_start = 0;
201-
202-
let mut first_iter_char = first_iter.next();
203-
let mut second_iter_char = second_iter.next();
204-
while first_iter_char.is_some() && first_iter_char == second_iter_char {
205-
first_iter_char = first_iter.next();
206-
second_iter_char = second_iter.next();
207-
limit_start += 1;
208-
}
209-
210-
// save char since the iterator was already consumed
211-
let first_iter_cache = first_iter_char;
212-
let second_iter_cache = second_iter_char;
213-
214-
if second_iter_char.is_some() && first_iter_char.is_some() {
215-
first_iter_char = first_iter.next_back();
216-
second_iter_char = second_iter.next_back();
217-
while first_iter_char.is_some() && first_iter_char == second_iter_char {
218-
first_iter_char = first_iter.next_back();
219-
second_iter_char = second_iter.next_back();
220-
}
221-
}
222-
223-
match (first_iter_char, second_iter_char) {
224-
(None, None) => {
225-
// characters might not match even though they were consumed
226-
let remaining_char = (first_iter_cache != second_iter_cache) as usize;
227-
Affix {
228-
prefix_len: limit_start,
229-
first_string_len: remaining_char,
230-
second_string_len: remaining_char,
231-
}
232-
}
233-
(None, _) => {
234-
let remaining_char =
235-
(first_iter_cache.is_some() && first_iter_cache != second_iter_char) as usize;
236-
Affix {
237-
prefix_len: limit_start,
238-
first_string_len: remaining_char,
239-
second_string_len: second_iter.count() + 1 + remaining_char,
240-
}
241-
}
242-
(_, None) => {
243-
let remaining_char =
244-
(second_iter_cache.is_some() && second_iter_cache != first_iter_char) as usize;
245-
Affix {
246-
prefix_len: limit_start,
247-
first_string_len: first_iter.count() + 1 + remaining_char,
248-
second_string_len: remaining_char,
249-
}
250-
}
251-
_ => Affix {
252-
prefix_len: limit_start,
253-
first_string_len: first_iter.count() + 2,
254-
second_string_len: second_iter.count() + 2,
255-
},
188+
let prefix_len = s1.iter()
189+
.zip(s2.iter())
190+
.take_while(|t| t.0 == t.1)
191+
.count();
192+
let suffix_len = s1[prefix_len..].iter()
193+
.rev()
194+
.zip(s2[prefix_len..].iter().rev())
195+
.take_while(|t| t.0 == t.1)
196+
.count();
197+
198+
Affix {
199+
prefix_len,
200+
suffix_len,
256201
}
257202
}
258203
}

0 commit comments

Comments
 (0)