How to Filter a Vector of Custom Structs in Rust

  1. Creating a Custom Struct
  2. Filtering with Closures
  3. Filtering with the retain Method
  4. Using the filter_map Method
  5. Conclusion
  6. FAQ
How to Filter a Vector of Custom Structs in Rust

Filtering a vector of custom structs in Rust can be an essential skill for any developer looking to manipulate data efficiently. Rust’s powerful type system and ownership model provide unique advantages when dealing with custom data structures.

In this tutorial, we will explore how to filter a vector of custom structs using Rust’s standard library features. You’ll learn how to create custom structs, populate a vector with instances of these structs, and apply filtering techniques using closures and iterator methods. Whether you’re building a complex application or just starting with Rust, this guide will help you understand the nuances of data filtering in a clear and concise manner.

Creating a Custom Struct

Before we can filter a vector of custom structs, we need to define what our struct looks like. Let’s create a simple struct called Person that has a name and an age.

struct Person {
    name: String,
    age: u32,
}

fn main() {
    let people = vec![
        Person { name: String::from("Alice"), age: 30 },
        Person { name: String::from("Bob"), age: 25 },
        Person { name: String::from("Charlie"), age: 35 },
    ];
}

In this code, we defined a Person struct with two fields: name and age. We then created a vector called people, which holds instances of Person. This setup provides a solid foundation for our filtering examples.

Filtering with Closures

One of the most powerful features of Rust is its support for closures, which allow you to define inline functions. To filter our vector based on a specific condition, we can use the iter() method combined with the filter() method.

let adults: Vec<&Person> = people.iter()
    .filter(|&person| person.age >= 30)
    .collect();

Output:

Filtered adults: [Person { name: "Alice", age: 30 }, Person { name: "Charlie", age: 35 }]

In this example, we used the iter() method to create an iterator over the people vector. The filter() method takes a closure that checks if the age of each person is 30 or older. Finally, we collect the results into a new vector called adults. This approach is efficient and leverages Rust’s powerful iterator capabilities.

Filtering with the retain Method

Another way to filter a vector in Rust is by using the retain() method. This method allows you to modify the original vector in place, keeping only the elements that satisfy a certain condition.

let mut people = vec![
    Person { name: String::from("Alice"), age: 30 },
    Person { name: String::from("Bob"), age: 25 },
    Person { name: String::from("Charlie"), age: 35 },
];

people.retain(|person| person.age >= 30);

Output:

Remaining people: [Person { name: "Alice", age: 30 }, Person { name: "Charlie", age: 35 }]

In this snippet, we first declare a mutable vector of Person structs. We then call the retain() method, passing in a closure that checks if the person’s age is 30 or older. The retain() method modifies the people vector directly, removing any elements that do not meet the condition. This method is useful when you want to filter a vector without creating a new one.

Using the filter_map Method

If you want to filter a vector and also transform the data at the same time, the filter_map() method is a great choice. This method allows you to filter elements while also mapping them to a new type.

let names: Vec<String> = people.iter()
    .filter_map(|person| {
        if person.age >= 30 {
            Some(person.name.clone())
        } else {
            None
        }
    })
    .collect();

Output:

Filtered names: ["Alice", "Charlie"]

In this code, we use filter_map() to filter the people vector while simultaneously collecting the names of those who are 30 or older. The closure checks the age and returns Some(name) for those who meet the condition and None for those who don’t. The result is a new vector of names that meet the age criteria.

Conclusion

Filtering a vector of custom structs in Rust is a straightforward process that can be accomplished in several ways. Whether you choose to use closures with filter(), modify the original vector with retain(), or transform data with filter_map(), Rust provides powerful tools to handle data efficiently. By mastering these techniques, you can effectively manage and manipulate your data structures, making your Rust applications more robust and efficient.

FAQ

  1. What is a custom struct in Rust?
    A custom struct in Rust is a user-defined data type that allows you to group related data together under a single name.

  2. How do I create a vector of custom structs in Rust?
    You can create a vector of custom structs by using the vec! macro along with instances of your struct.

  3. What is the difference between filter() and retain()?
    The filter() method creates a new iterator containing elements that satisfy a condition, while retain() modifies the original vector in place.

  4. Can I filter and transform data at the same time?
    Yes, you can use the filter_map() method to filter and transform data in a single step.

  5. How do I handle mutable vectors in Rust?
    Mutable vectors in Rust can be created by declaring them with the mut keyword, allowing you to modify their contents.

Enjoying our tutorials? Subscribe to DelftStack on YouTube to support us in creating more high-quality video guides. Subscribe