mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-12 07:24:11 +00:00
merge: extract trivial_merge() that takes interleaved adds/removes iterator
The Merge type will store interleaved terms instead of separate adds/removes vecs.
This commit is contained in:
parent
01523ba4f3
commit
287728fee7
1 changed files with 23 additions and 15 deletions
|
@ -43,17 +43,28 @@ where
|
||||||
removes.len() + 1,
|
removes.len() + 1,
|
||||||
"trivial_merge() requires exactly one more adds than removes"
|
"trivial_merge() requires exactly one more adds than removes"
|
||||||
);
|
);
|
||||||
|
trivial_merge_inner(
|
||||||
|
itertools::interleave(adds, removes),
|
||||||
|
adds.len() + removes.len(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trivial_merge_inner<T>(mut values: impl Iterator<Item = T>, values_len: usize) -> Option<T>
|
||||||
|
where
|
||||||
|
T: Eq + Hash,
|
||||||
|
{
|
||||||
// Optimize the common cases of 3-way merge and 1-way (non-)merge
|
// Optimize the common cases of 3-way merge and 1-way (non-)merge
|
||||||
if adds.len() == 1 {
|
if values_len == 1 {
|
||||||
return Some(&adds[0]);
|
let add = values.next().unwrap();
|
||||||
} else if adds.len() == 2 {
|
return Some(add);
|
||||||
return if adds[0] == adds[1] {
|
} else if values_len == 3 {
|
||||||
Some(&adds[0])
|
let (add0, remove, add1) = values.next_tuple().unwrap();
|
||||||
} else if adds[0] == removes[0] {
|
return if add0 == add1 {
|
||||||
Some(&adds[1])
|
Some(add0)
|
||||||
} else if adds[1] == removes[0] {
|
} else if add0 == remove {
|
||||||
Some(&adds[0])
|
Some(add1)
|
||||||
|
} else if add1 == remove {
|
||||||
|
Some(add0)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -62,12 +73,9 @@ where
|
||||||
// Number of occurrences of each value, with positive indexes counted as +1 and
|
// Number of occurrences of each value, with positive indexes counted as +1 and
|
||||||
// negative as -1, thereby letting positive and negative terms with the same
|
// negative as -1, thereby letting positive and negative terms with the same
|
||||||
// value (i.e. key in the map) cancel each other.
|
// value (i.e. key in the map) cancel each other.
|
||||||
let mut counts: HashMap<&T, i32> = HashMap::new();
|
let mut counts: HashMap<T, i32> = HashMap::new();
|
||||||
for value in adds.iter() {
|
for (value, n) in zip(values, [1, -1].into_iter().cycle()) {
|
||||||
counts.entry(value).and_modify(|e| *e += 1).or_insert(1);
|
counts.entry(value).and_modify(|e| *e += n).or_insert(n);
|
||||||
}
|
|
||||||
for value in removes.iter() {
|
|
||||||
counts.entry(value).and_modify(|e| *e -= 1).or_insert(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect non-zero value. Values with a count of 0 means that they have
|
// Collect non-zero value. Values with a count of 0 means that they have
|
||||||
|
|
Loading…
Reference in a new issue