sort_by_borrowed_key/
lib.rs

1/// A crate to add two more sorting methods
2/// ---
3///
4/// Say you have a vector of tuples, which you would like to sort by one of the
5/// elements (maybe you got it by using the enumerate or zip iterator methods,
6/// then collected into a Vec). Now, if you write the following, you will get
7/// lifetime errors:
8/// ```compile_fail
9/// let mut letters = vec![
10///     (1, "C".to_string()), 
11///     (2, "B".to_string()),
12///     (3, "B".to_string()),
13///     (4, "A".to_string())
14/// ];
15/// letters.sort_by_key(|x| &x.1);
16/// println!("Letters: {:?}", letters);
17/// ```
18/// So you might try not borrowing, but then you realize String isn't Copy:
19/// ```compile_fail
20/// let mut letters = vec![
21///     (1, "C".to_string()), 
22///     (2, "B".to_string()),
23///     (3, "B".to_string()),
24///     (4, "A".to_string())
25/// ];
26/// letters.sort_by_key(|x| x.1);
27/// println!("Letters: {:?}", letters);
28/// ```
29/// So this fails because you'd be moving out of the array! You don't want to 
30/// have to expensively clone all of these strings just to compare them. That's
31/// where this library comes in:
32/// ```
33/// use sort_by_borrowed_key::SortByBorrowedKey;
34/// let mut letters = vec![
35///     (1, "C".to_string()), 
36///     (2, "B".to_string()),
37///     (3, "B".to_string()),
38///     (4, "A".to_string())
39/// ];
40/// letters.sort_by_borrowed_key(|x| &x.1);
41/// let expected = vec![
42///     (4, "A".to_string()), 
43///     (2, "B".to_string()),
44///     (3, "B".to_string()),
45///     (1, "C".to_string())
46/// ];
47/// assert_eq!(letters, expected);
48/// ```
49/// That's it! The only other thing this crate adds is a unstable-sort version
50/// of the same method, `sort_unstable_by_borrowed_key`, which is faster but may
51/// change of the order of equal elements (see the docs for
52/// `[T]::sort_unstable`).
53///
54pub trait SortByBorrowedKey<T> {
55    fn sort_by_borrowed_key<K, F>(&mut self, f: F) where
56        F: for<'a> Fn(&'a T) -> &'a K,
57        K: Ord;
58    fn sort_unstable_by_borrowed_key<K, F>(&mut self, f: F) where
59        F: for<'a> Fn(&'a T) -> &'a K,
60        K: Ord;
61}
62
63impl<T> SortByBorrowedKey<T> for [T] {
64    fn sort_by_borrowed_key<K, F>(&mut self, f: F) where
65        F: for<'a> Fn(&'a T) -> &'a K,
66        K: Ord {
67            self.sort_by(|a, b| {
68                f(a).cmp(f(b))
69            });
70        }
71    fn sort_unstable_by_borrowed_key<K, F>(&mut self, f: F) where
72        F: for<'a> Fn(&'a T) -> &'a K,
73        K: Ord {
74            self.sort_unstable_by(|a, b| {
75                f(a).cmp(f(b))
76            });
77        }
78}
79
80#[cfg(test)]
81mod tests {
82    use crate::*;
83    #[test]
84    fn test_stable() {
85        let mut letters = vec![
86            (1, "C".to_string()), 
87            (2, "B".to_string()),
88            (3, "B".to_string()),
89            (4, "A".to_string())
90        ];
91        letters.sort_by_borrowed_key(|x| &x.1);
92        let expected = vec![
93            (4, "A".to_string()), 
94            (2, "B".to_string()),
95            (3, "B".to_string()),
96            (1, "C".to_string())
97        ];
98        assert_eq!(letters, expected);
99    }
100}