Function hyper_scripter::fuzzy::is_prefix
source · Examples found in repository?
src/query/the_multifuzz_algo.rs (line 53)
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
fn find_dag_sink<T: MultiFuzzObj>(
offset: usize,
candidates: &mut [MultiFuzzTuple<T>],
best_sink: &mut Option<usize>,
) {
candidates[offset].visited = true;
let cur_key = candidates[offset].fuzz_key();
// SAFETY: 同一個元素的鍵不可能被拜訪第二次,而且唯一的可變性發生在 `visited` 欄位
let cur_key = unsafe { &*(cur_key.as_ref() as *const str) };
let mut prefix_found = false;
for i in offset + 1..candidates.len() {
if candidates[i].visited {
continue;
}
let other_key = candidates[i].fuzz_key();
if other_key.len() != cur_key.len() && is_prefix(&other_key, cur_key, SEP) {
prefix_found = true;
find_dag_sink(i, candidates, best_sink);
}
}
if !prefix_found {
// 沉沒點!
if let Some(best_sink) = best_sink {
if candidates[offset].obj.beats(&candidates[*best_sink].obj) {
*best_sink = offset;
}
} else {
*best_sink = Some(offset)
}
}
}
/// with several elements equally maximum, the **FIRST** position will be returned
fn find_max_and_ans_pos<T: MultiFuzzObj>(candidates: &[MultiFuzzTuple<T>]) -> (usize, usize) {
let mut max_pos = 0;
let mut ans_pos = 0;
for i in 1..candidates.len() {
if candidates[i].is_ans {
ans_pos = i;
}
if candidates[i].obj.beats(&candidates[max_pos].obj) {
max_pos = i;
}
}
(max_pos, ans_pos)
}
/// 從多個模糊搜分數相近者中裁決出「最合適者」。函式過程不太直覺,故在此詳述。
/// 參數:正解(ans)即分數最高者,其它(others)即其它分數相近的候選人。
/// 應保證正解的長度不大於所有其它人
///
/// 1. 建立一個有向無環圖,從「最強者」(根據 MultiFuzzObj::beats)出發,找到所有沉沒點
/// 2. 於所有沉沒點中選出最強者
/// 3. 若最強者為正解之前綴(重排序),回傳正解
pub(super) fn the_multifuzz_algo<T: MultiFuzzObj>(ans: T, others: Vec<T>) -> T {
let mut candidates: Vec<_> = others.into_iter().map(|t| MultiFuzzTuple::new(t)).collect();
candidates.push(MultiFuzzTuple::new_ans(ans));
candidates.sort_by(MultiFuzzTuple::cmp);
let (max_pos, ans_pos) = find_max_and_ans_pos(&candidates);
let mut ret_pos = None;
find_dag_sink(max_pos, &mut candidates, &mut ret_pos);
let mut ret_pos = ret_pos.unwrap();
if is_prefix(
&candidates[ret_pos].fuzz_key(),
&candidates[ans_pos].fuzz_key(),
SEP,
) {
ret_pos = ans_pos;
}
candidates.into_iter().skip(ret_pos).next().unwrap().obj
}More examples
src/util/completion_util.rs (line 45)
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
async fn fuzz_arr<'a>(
name: &str,
iter: impl Iterator<Item = RepoEntry<'a>>,
) -> Result<Vec<RepoEntry<'a>>> {
// TODO: 測試這個複雜的函式,包括前綴和次級結果
let res = fuzz_with_multifuzz_ratio(name, iter, SEP, Some(60)).await?;
Ok(match res {
None => vec![],
Some(FuzzResult::High(t) | FuzzResult::Low(t)) => vec![t],
Some(FuzzResult::Multi {
ans,
others,
mut still_others,
}) => {
let prefix = ans.name.key();
let mut first_others = vec![];
let mut prefixed_others = vec![];
for candidate in others.into_iter() {
if is_prefix(&*prefix, &*candidate.name.key(), SEP) {
prefixed_others.push(candidate);
} else {
first_others.push(candidate);
}
}
first_others.push(ans);
sort(&mut first_others);
sort(&mut prefixed_others);
sort(&mut still_others);
first_others.append(&mut prefixed_others);
first_others.append(&mut still_others);
first_others
}
})
}