refactor: simplify the code

This commit is contained in:
sxyazi 2024-10-29 12:55:46 +08:00
parent d6ea209690
commit c0d67428f4
No known key found for this signature in database

View file

@ -53,7 +53,7 @@ impl Manager {
return Ok(()); return Ok(());
} }
let todo = Self::sort(old, new); let todo = Self::prioritized_paths(old, new);
if todo.is_empty() { if todo.is_empty() {
return Ok(()); return Ok(());
} }
@ -118,46 +118,38 @@ impl Manager {
Ok(()) Ok(())
} }
fn sort(old: Vec<PathBuf>, new: Vec<PathBuf>) -> Vec<(PathBuf, PathBuf)> { fn prioritized_paths(old: Vec<PathBuf>, new: Vec<PathBuf>) -> Vec<(PathBuf, PathBuf)> {
let user_order: HashMap<_, _> = old.iter().enumerate().map(|(idx, path)| (path, idx)).collect(); let orders: HashMap<_, _> = old.iter().enumerate().map(|(i, p)| (p, i)).collect();
let mut income_map: HashMap<_, _> = old.iter().map(|path| (path.clone(), false)).collect(); let mut incomes: HashMap<_, _> = old.iter().map(|p| (p, false)).collect();
let mut todos: HashMap<_, _> = old let mut todos: HashMap<_, _> = old
.iter() .iter()
.zip(new) .zip(new)
.map(|(old, new)| { .map(|(o, n)| {
if let Some(has_income) = income_map.get_mut(&new) { incomes.get_mut(&n).map(|b| *b = true);
*has_income = true; (o, n)
}
(old.clone(), new)
}) })
.collect(); .collect();
let mut sorted = vec![]; let mut sorted = Vec::with_capacity(old.len());
while !todos.is_empty() { while !todos.is_empty() {
let mut has_no_incomes = vec![]; // Paths that are non-incomes and don't need to be prioritized in this round
income_map.iter().for_each(|(old, has_income)| { let mut outcomes: Vec<_> = incomes.iter().filter(|(_, &b)| !b).map(|(&p, _)| p).collect();
if !has_income { outcomes.sort_unstable_by(|a, b| orders[b].cmp(&orders[a]));
has_no_incomes.push(old.clone())
}
});
if has_no_incomes.is_empty() { // If there're no outcomes, it means there are cycles in the renaming
// Remaining rename set has cycle, so we cannot sort, just return them all if outcomes.is_empty() {
let mut remain = todos.drain().collect::<Vec<_>>(); let mut remain: Vec<_> = todos.into_iter().map(|(o, n)| (o.clone(), n)).collect();
remain.sort_by(|(a, _), (b, _)| user_order[a].cmp(&user_order[b])); remain.sort_unstable_by(|(a, _), (b, _)| orders[a].cmp(&orders[b]));
sorted.reverse(); sorted.reverse();
sorted.extend(remain); sorted.extend(remain);
return sorted; return sorted;
} }
has_no_incomes.sort_by(|a, b| user_order[b].cmp(&user_order[a])); for old in outcomes {
for old in has_no_incomes { let Some(new) = todos.remove(old) else { unreachable!() };
income_map.remove(&old); incomes.remove(&old);
let Some(new) = todos.remove(&old) else { unreachable!("") }; incomes.get_mut(&new).map(|b| *b = false);
if let Some(has_income) = income_map.get_mut(&new) { sorted.push((old.clone(), new));
*has_income = false;
}
sorted.push((old, new));
} }
} }
sorted.reverse(); sorted.reverse();
@ -172,7 +164,7 @@ mod tests {
#[test] #[test]
fn test_sort() { fn test_sort() {
fn cmp(input: &[(&str, &str)], expected: &[(&str, &str)]) { fn cmp(input: &[(&str, &str)], expected: &[(&str, &str)]) {
let sorted = Manager::sort( let sorted = Manager::prioritized_paths(
input.iter().map(|&(o, _)| o.into()).collect(), input.iter().map(|&(o, _)| o.into()).collect(),
input.iter().map(|&(_, n)| n.into()).collect(), input.iter().map(|&(_, n)| n.into()).collect(),
); );