use std::cmp::Ordering;
pub fn k_way_merge<T, F, S>(per_worker: Vec<Vec<T>>, cmp: F, mut sink: S)
where
F: Fn(&T, &T) -> Ordering,
S: FnMut(T),
{
let mut iters: Vec<_> = per_worker.into_iter().map(Vec::into_iter).collect();
let mut heads: Vec<Option<T>> = iters.iter_mut().map(Iterator::next).collect();
while let Some(best) = heads
.iter()
.enumerate()
.filter_map(|(i, h)| h.as_ref().map(|v| (i, v)))
.min_by(|(_, a), (_, b)| cmp(a, b))
.map(|(i, _)| i)
{
sink(heads[best].take().unwrap());
heads[best] = iters[best].next();
}
}
pub fn topk<T, F>(mut rows: Vec<T>, k: usize, cmp: F) -> Vec<T>
where
F: Fn(&T, &T) -> Ordering,
{
if k == 0 {
rows.clear();
} else if rows.len() > k {
rows.select_nth_unstable_by(k, |a, b| cmp(a, b));
rows.truncate(k);
}
rows.sort_by(|a, b| cmp(a, b));
rows
}