///|
/// Sorted, nonzero sums of weights for each equal key; input array is unchanged.
pub fn[D : Compare, R : Semigroup] consolidate(
input : Array[(D, R)],
) -> Array[(D, R)] {
let sorted = input.copy()
sorted.sort_by(fn(a, b) { a.0.compare(b.0) })
let output : Array[(D, R)] = []
for (key, diff) in sorted {
if output.last() is Some((previous, accumulated)) && previous == key {
let _ = output.pop()
let sum = accumulated.plus(diff)
if !sum.is_zero() {
output.push((key, sum))
}
} else if !diff.is_zero() {
output.push((key, diff))
}
}
output
}
///|
/// Consolidates by record and timestamp, retaining incomparable times separately.
pub fn[D : Compare, T : Compare, R : Semigroup] consolidate_updates(
input : Array[(D, T, R)],
) -> Array[(D, T, R)] {
consolidate(input.map(fn(u) { ((u.0, u.1), u.2) })).map(fn(u) {
(u.0.0, u.0.1, u.1)
})
}