In Rust, we can compare if two struct instances are equivalent and whose respective field values are the same. However, doing so requires using traits.
Equivalent vs. Partial Equivalent
Before we proceed, let us differentiate between Equivalent and Partial Equivalent. When two struct instances are equivalent across all corresponding field values, they are Equivalent.
On the other hand, when two struct instances are equivalent across only some field values, they are Partial(ly) Equivalent. In Rust, Equivalent and Partial Equivalent are these traits – Eq and PartialEq, respectively, and we can use them to compare struct instances.
Compare Struct Instances with Equivalent in Rust
We have the following struct to represent a point in an X-Y graph. In this case, two (2) instances of the Point struct are the same if and only if they have the same values for x and y.
1 2 3 4 | struct Point { x: i32, y: i32 } |
To make two Rust struct Point instances equivalent when comparing them, we need to modify the struct to the following.
1 2 3 4 5 | #[derive(Eq, PartialEq)] struct Point { x: i32, y: i32 } |
That is all! We can now test with some data. However, there is a problem with this technique in Rust – we cannot customize how we compare the instances. We will revisit that issue later on in this post.
Now, why are we using two traits? As of Rust 1.59.0, we need to use both Eq and PartialEq.
Let’s test some Rust codes – consider the following.
1 2 3 4 5 6 7 8 9 10 11 12 13 | let point_3_4 = Point{ x: 3, y: 4}; let point_neg3_10 = Point{ x: -3, y: 10}; let find_point_3_4 = Point{ x: 3, y: 4}; println!("find_point_3_4 is equivalent to point_3_4? {}", point_3_4 == find_point_3_4); println!("find_point_3_4 is equivalent to point_neg3_10? {}", point_neg3_10 == find_point_3_4); let mut point_list:Vec<Point> = Vec::new(); point_list.push(point_3_4); point_list.push(point_neg3_10); println!("Is find_point_3_4 in point_list? {}", point_list.contains(&find_point_3_4)); |
When we run these codes, we get the following output.
1 2 3 | find_point_3_4 is equivalent to point_3_4? true find_point_3_4 is equivalent to point_neg3_10? false Is find_point_3_4 in point_list? true |
Compare Struct Instances with Partial(ly) Equivalent in Rust
For this purpose, we want to compare two Rust struct instances partially equivalent to student_id.
1 2 3 4 5 | #[derive(Debug)] struct Student { student_id: i32, student_name: String } |
We need to implement the PartialEq trait.
1 2 3 4 5 6 | impl PartialEq for Student { fn eq(&self, other: &Self) -> bool { self.student_id == other.student_id } } |
Note that we are now using the Student struct for this part.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | let student1 = Student{student_id:1, student_name: "Karl".to_string()}; let student2 = Student{student_id:2, student_name: "Max".to_string()}; let student3 = Student{student_id:3, student_name: "Pedro".to_string()}; // student_id = 1 but student_name is "Annie" let find_student = Student{student_id:1, student_name: "Annie".to_string()}; if student1 == student2 { println!("{:?} and {:?} are equivalent", student1, student2); } else { println!("{:?} and {:?} are not equivalent", student1, student2); } let mut list: Vec<Student> = Vec::new(); list.push(student1); list.push(student2); list.push(student3); println!("{:?} is found in list {}", find_student, list.contains(&find_student)); |
Output
1 2 | Student { student_id: 1, student_name: "Karl" } and Student { student_id: 2, student_name: "Max" } are not equivalent Student { student_id: 1, student_name: "Annie" } is found in list true |
And that is how we compare struct instances using traits!
Please read Check if a key exists in HashMap Examples for more examples. There are example codes that use struct instances as keys in HashMap. As keys, we need to compare these instances to retrieve their respective values from the HashMap instance.