0

The Rust's HashSet::intersection function creates a new HashSet. How can I update original HashSet by the result of intersection of two HashSets?

fn main() {
    // intersecting two HashSets, creating a new HashSet: OK
    use std::collections::HashSet;
    let a = HashSet::from(["first", "second", "third"]);
    let b = HashSet::from(["first", "third", "fifth", "ninth"]);
    let intersection: HashSet<_> = a.intersection(&b).collect();
    println!("{:?}", intersection);

    
    // intersecting two HashSets, updating the original HashSet: Failed
    let mut a = HashSet::from(["first", "second", "third"]);
    let b = HashSet::from(["first", "third", "fifth", "ninth"]);
    println!("{:?}", a.intersection(&b).collect::<HashSet<_>>());
    println!("{:?}", a);
    a = a.intersection(&b).collect::<HashSet<_>>();  // doesn't work

    // filter: verbose
    let mut a = HashSet::from(["first", "second", "third"]);
    let b = HashSet::from(["first", "third", "fifth", "ninth"]);
    a = a.iter().filter(|&s| b.contains(s)).map(|s| *s).collect::<HashSet<_>>();
    println!("{:?}", a);
}
Larynx
  • 398
  • 1
  • 12

1 Answers1

3

To do this without allocating a new HashSet, you can use HashSet::retain and only retain the elements that exist in the second HashSet:

fn main() {
    use std::collections::HashSet;
    let mut a = HashSet::from(["first", "second", "third"]);
    let b = HashSet::from(["first", "third", "fifth", "ninth"]);
    println!("{:?}", a.intersection(&b).collect::<HashSet<_>>());
    a.retain(|x| b.contains(x));
    println!("{:?}", a);
}

Output:

{"third", "first"}
{"first", "third"}

Playground

Dogbert
  • 212,659
  • 41
  • 396
  • 397