Искаме да напишете итератор, който разбива една дума на триграми. Ето едно обяснение на това какво
е "триграма", от postgresql
документацията:
A trigram is a group of three consecutive characters taken from a string. We can measure the similarity of two strings by counting the number of trigrams they share. This simple idea turns out to be very effective for measuring the similarity of words in many natural languages.
Each word is considered to have two spaces prefixed and one space suffixed when determining the set of trigrams contained in the string. For example, the set of trigrams in the string "cat" is " c", " ca", "cat", and "at ".
Тоест, очакваме да генерирате всички поредици от три символа, които се намират в думата, която ви подаваме. Като специални случаи:
първата триграма е два интервала и първия символ, ако има първи символ (в горния пример -- " c")
вторатa триграма е един интервал и първите два символа, ако има поне два символа (в горния пример -- " ca")
последната триграма е последните два символа и интервал, ако има поне два символа (в горния пример -- "at ")
Тестовете ще се викат само с валидни думи (само char::is_alphabetic символи), само с малки букви, така че не се притеснявайте за специални символи или вътрешни интервали, и не мислете за case-sensitivity. Все пак, както винаги, мислете за edge cases.
Следва интерфейса, който очакваме. Забележете, че резултата, който се връща от next е String, а не &str -- заради интервалите в началото и края. Това значи, че, на теория, бихте могли да го имплементирате по сравнително лесен и неефективен начин. Бихме искали да не го правите, но не можахме да измислим начин да ви спрем :). Все пак бихме предпочели да итерирате максимално ефективно по низа, и се надяваме и вие да предпочитате същото.
// Lifetime-а е да ви стимулира да пазите някаква форма на reference към оригиналната дума. Може би
// &'a str, а може би Chars<'a>? Ако случайно не ви трябва, махнете си го.
//
pub struct TrigramIterator<'a> {
// ...
}
impl<'a> TrigramIterator<'a> {
pub fn new(word: &'a str) -> Self {
// ...
}
}
impl<'a> Iterator for TrigramIterator<'a> {
type Item = String;
fn next(&mut self) -> Option<Self::Item> {
// ...
}
}