Skip to content

Instantly share code, notes, and snippets.

@AnthonyMikh
Created April 9, 2022 00:42
Show Gist options
  • Save AnthonyMikh/ee39e5e05072b9bfb6f4d53c61318caa to your computer and use it in GitHub Desktop.
Save AnthonyMikh/ee39e5e05072b9bfb6f4d53c61318caa to your computer and use it in GitHub Desktop.
Sorting by borrowed key (advanced variant requires GATs)
#![feature(generic_associated_types)]
pub struct Data {
pub name: String,
pub whatever: u32,
pub bytes: Vec<u8>,
}
trait BorrowedKeyFamily {
type Key<'a>: Ord + 'a;
}
struct PairRef<T, U: ?Sized>(std::marker::PhantomData<(T, U)>);
impl<T, U> BorrowedKeyFamily for PairRef<T, U>
where
T: Ord + 'static,
U: Ord + 'static + ?Sized,
{
type Key<'a> = (&'a T, &'a U);
}
trait SliceExt<T> {
fn sort_by_ref_key<K, F>(&mut self, f: F)
where
F: FnMut(&T) -> &K,
K: Ord + ?Sized;
fn sort_by_borrowed_key<K, F>(&mut self, f: F)
where
F: for<'a> FnMut(&'a T) -> K::Key<'a>,
K: BorrowedKeyFamily;
}
impl<T> SliceExt<T> for [T] {
fn sort_by_ref_key<K, F>(&mut self, mut f: F)
where
F: FnMut(&T) -> &K,
K: Ord + ?Sized,
{
self.sort_by(|a, b| f(a).cmp(&f(b)));
}
fn sort_by_borrowed_key<K, F>(&mut self, mut f: F)
where
F: FnMut(&T) -> K::Key<'_>,
K: BorrowedKeyFamily,
{
self.sort_by(|a, b| f(a).cmp(&f(b)));
}
}
pub fn sort_by_name(arr: &mut [Data]) {
arr.sort_by(|a, b| a.name.cmp(&b.name));
}
pub fn sort_by_name_fancy(arr: &mut [Data]) {
arr.sort_by_ref_key(|d| &d.name);
}
pub fn sort_by_name_and_bytes(arr: &mut [Data]) {
arr.sort_by(|a, b| (&a.name, &a.bytes).cmp(&(&b.name, &b.bytes)));
}
pub fn sort_by_name_and_bytes_fancy(arr: &mut [Data]) {
arr.sort_by_borrowed_key::<PairRef<_, _>, _>(|d| (&d.name, &d.bytes));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment