ender maz
ender maz

Reputation: 393

How do I filter a vector of an enum of different structs using a common field?

I found you can create a vector of different types of structs using an enum. When filtering the vector on a common field, such as id, the compiler doesn't know the type while iterating:

use chrono::{DateTime, Utc}; // 0.4.19
use serde::{Serialize, Deserialize}; // 1.0.126

#[derive(Deserialize, Debug, Serialize, Clone)]
pub enum TransactionsEnum {
    TransactionOrderA(TransactionOrderA),
    TransactionOrderB(TransactionOrderB),
}
#[derive(Deserialize, Debug, Serialize, Clone)]
pub struct TransactionOrderA {
    pub id: i64,
    pub accountID: String,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct TransactionOrderB {
    pub id: i64,
    pub time: DateTime<Utc>,
}

fn transactions_filter(
    transactions_vector: Vec<TransactionsEnum>,
    x: i64,
) -> Vec<TransactionsEnum> {
    transactions_vector
        .into_iter()
        .filter(|e| e.id >= x)
        .collect()
}
error[E0609]: no field `id` on type `&TransactionsEnum`
  --> src/lib.rs:27:23
   |
27 |         .filter(|e| e.id >= x)
   |                       ^^

Sharing a common value in all enum values and Is there a way to directly access a field value in an enum struct without pattern matching? indirectly answer my question, but the answer provided here helped me understand why a match statement is necessary.

Upvotes: 1

Views: 1985

Answers (1)

Silvio Mayolo
Silvio Mayolo

Reputation: 70277

Those are not a common field, they are completely unrelated fields. The fact that they share a name is, as far as the Rust compiler is concerned, an insignificant coincidence. You need to use pattern matching to get the field from either case

impl TransactionsEnum {
    pub fn id(&self) -> i64 {
        match self {
            TransactionsEnum::TransactionOrderA(value) => value.id,
            TransactionsEnum::TransactionOrderB(value) => value.id,
        }
    }
}
transactions_vector
    .into_iter()
    .filter(|e| e.id() >= x) // Note the parentheses since we're calling a function now
    .collect()

Upvotes: 3

Related Questions