Vec::dedup_by_key¶
Level: reference · for working programmers
One line: dedup comparing a derived key rather than the whole element.
Stable since 1.16.0.
Collapses consecutive runs whose key is equal, keeping the first element of each run. v.dedup_by_key(|r| r.id) is the readable way to say "one row per id" over data already grouped by id.
Consecutive, still: sort by the same key first if the runs are not already together.
The closure takes &mut T, so it may normalise on the way past — lowercasing a name and deduping on the result in one call.
The key type needs only PartialEq — not Ord, not Hash — so a key can be a tuple, a bool, or any small struct that derives PartialEq.
Equivalent to dedup_by(|a, b| key(a) == key(b)), and clearer whenever a key function exists.
Example¶
vec_dedup_by_key.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
// Collapse consecutive runs that map to the same key.
let mut v = vec![10, 16, 20, 21, 30];
v.dedup_by_key(|n| *n / 10);
println!("{v:?}");
// The element kept from each run is the FIRST one.
#[derive(Debug)]
struct Row { id: u8, note: &'static str }
let mut rows = vec![
Row { id: 1, note: "first" },
Row { id: 1, note: "second" },
Row { id: 2, note: "third" },
];
rows.dedup_by_key(|r| r.id);
println!("{:?}", rows.iter().map(|r| (r.id, r.note)).collect::<Vec<_>>());
// Consecutive, still. Sort by the key first if the runs are not grouped.
let mut v = vec![("b", 1), ("a", 2), ("b", 3)];
v.dedup_by_key(|p| p.0);
println!("ungrouped: {v:?}");
let mut v = vec![("b", 1), ("a", 2), ("b", 3)];
v.sort_by_key(|p| p.0);
v.dedup_by_key(|p| p.0);
println!("sorted first: {v:?}");
// The closure gets &mut T, so it may normalise on the way past.
let mut names = vec![String::from("Ada"), String::from("ADA"), String::from("Ben")];
names.dedup_by_key(|s| { *s = s.to_lowercase(); s.clone() });
println!("{names:?}");
// The key type only needs PartialEq, not Ord or Hash.
#[derive(PartialEq)]
struct Key(bool);
let mut flags = vec![0, 2, 4, 5, 7, 8];
flags.dedup_by_key(|n| Key(*n % 2 == 0));
println!("runs of even/odd: {flags:?}");
}
Verified output of vec_dedup_by_key.rs — regenerated by tools/run_examples.py, never hand-typed.
[10, 20, 30]
[(1, "first"), (2, "third")]
ungrouped: [("b", 1), ("a", 2), ("b", 3)]
sorted first: [("a", 2), ("b", 1)]
["ada", "ben"]
runs of even/odd: [0, 5, 8]
See also¶
Vec::dedup— comparing whole elementsVec::dedup_by— when the comparison is not a key equalityslice::sort_by_key↗ — the call that usually comes first