Rust 验证具有vec中关联值的枚举的唯一性

Rust 验证具有vec中关联值的枚举的唯一性,rust,Rust,下面是我定义了一个输入类型为Vec的方法的代码。此方法应验证arm(不检查关联值)是否必须唯一。这意味着它应该包含最多一个比萨饼,一个蛋糕和一个地铁注意:不需要所有手臂都在Vec中。我在下面的代码中也写了一些测试,它们仍然需要通过 我的“真实”代码中有更多的enum arms,而我当前的方法伸缩性不是很好,所以我希望有一种更简单的方法 fn main() { } enum Food { Cake(String), Pizza(i32), Subway(u64) }

下面是我定义了一个输入类型为
Vec
的方法的代码。此方法应验证arm(不检查关联值)是否必须唯一。这意味着它应该包含最多一个比萨饼,一个蛋糕和一个地铁注意:不需要所有手臂都在
Vec
中。我在下面的代码中也写了一些测试,它们仍然需要通过

我的“真实”代码中有更多的enum arms,而我当前的方法伸缩性不是很好,所以我希望有一种更简单的方法

fn main() {

}

enum Food {
    Cake(String),
    Pizza(i32),
    Subway(u64)
}

struct CustomError;

fn validate(foods: Vec<Food>) -> Result<(), CustomError> {
    let mut cake = false;
    let mut pizza = false;
    let mut subway = false;

    for f in foods.iter() {
        match f {
            Food::Cake(_) => {
                if cake {
                    return Err(CustomError)
                }

                cake = true;
            },
            Food::Pizza(_) => {
                if pizza {
                    return Err(CustomError)
                }

                pizza = true;
            },
            Food::Subway(_) => {
                if subway {
                    return Err(CustomError)
                }

                subway = true;
            },
        }
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test() {
        assert!(validate(vec![Food::Pizza(1)]).is_ok());
        assert!(validate(vec![Food::Pizza(1), Food::Cake("Apple".to_owned())]).is_ok());
        assert!(validate(vec![]).is_ok());

        assert!(validate(vec![Food::Pizza(1), Food::Pizza(1)]).is_err());
        assert!(validate(vec![Food::Pizza(1), Food::Pizza(2)]).is_err());
    }
}
fn main(){
}
列举食物{
蛋糕(线),
比萨饼(i32),
地铁(u64)
}
结构自定义错误;
fn验证(食品:Vec)->结果{
让mut-cake=false;
让mut=false;
设mut=false;
用于食品中的f。iter(){
匹配f{
食物:蛋糕(=>{
如果蛋糕{
返回错误(自定义错误)
}
蛋糕=真;
},
食物:比萨饼()=>{
如果披萨{
返回错误(自定义错误)
}
比萨饼=真;
},
食物:地铁{
如果地铁{
返回错误(自定义错误)
}
地铁=正确;
},
}
}
好(())
}
#[cfg(测试)]
模试验{
使用超级::*;
#[测试]
fn测试(){
断言!(验证(vec![Food::Pizza(1)])。是否正常();
断言!(验证(vec![Food::Pizza(1),Food::蛋糕(“Apple.”to_owned()))。是否正常();
断言!(验证(vec![])。是否正常();
断言!(验证(vec![Food::Pizza(1),Food::Pizza(1)]).is_err();
断言!(验证(vec![Food::Pizza(1),Food::Pizza(2)]).is_err();
}
}

Rust没有太多的反射功能,因此我认为您最好编写类似于a的代码来生成包含match语句的函数,而您描述的match语句不想手动编写。

Rust没有太多的反射功能,因此,我认为最好的方法是编写类似于a的代码,生成一个函数,其中包含您描述的不希望手动编写的match语句。

要比较
enum
变量而不考虑任何相关数据,该函数非常有用。给定一个
enum
类型的值,
std::mem::discriminant
返回一个类型的值,该值告诉该值是哪个变量
std::mem::Discriminant
实现了
Hash
,因此我们可以在
HashSet
中保留到目前为止看到的所有变体,以检查是否存在任何重复

只是一个小技巧:
HashSet::insert
返回一个布尔值,当插入的元素不在集合中时,该布尔值为true。这意味着我们可以将检查是否已看到鉴别器和插入新鉴别器的步骤结合起来

use std::collections::HashSet;
use std::mem::discriminant;

enum Food {
    Cake(String),
    Pizza(i32),
    Subway(u64),
}

struct CustomError;

fn validate(foods: Vec<Food>) -> Result<(), CustomError> {
    let mut discriminants = HashSet::new();
    for food in foods {
        if !discriminants.insert(discriminant(&food)) {
            return Err(CustomError);
        }
    }
    Ok(())
}
使用std::collections::HashSet;
使用std::mem::discriminant;
列举食物{
蛋糕(线),
比萨饼(i32),
地铁(u64),
}
结构自定义错误;
fn验证(食品:Vec)->结果{
让mut discriminants=HashSet::new();
食物中的食物{
如果!判别式。插入(判别式(&食物)){
返回错误(CustomError);
}
}
好(())
}

要比较
enum
变量而不关心任何相关数据,该函数非常有用。给定一个
enum
类型的值,
std::mem::discriminant
返回一个类型的值,该值告诉该值是哪个变量
std::mem::Discriminant
实现了
Hash
,因此我们可以在
HashSet
中保留到目前为止看到的所有变体,以检查是否存在任何重复

只是一个小技巧:
HashSet::insert
返回一个布尔值,当插入的元素不在集合中时,该布尔值为true。这意味着我们可以将检查是否已看到鉴别器和插入新鉴别器的步骤结合起来

use std::collections::HashSet;
use std::mem::discriminant;

enum Food {
    Cake(String),
    Pizza(i32),
    Subway(u64),
}

struct CustomError;

fn validate(foods: Vec<Food>) -> Result<(), CustomError> {
    let mut discriminants = HashSet::new();
    for food in foods {
        if !discriminants.insert(discriminant(&food)) {
            return Err(CustomError);
        }
    }
    Ok(())
}
使用std::collections::HashSet;
使用std::mem::discriminant;
列举食物{
蛋糕(线),
比萨饼(i32),
地铁(u64),
}
结构自定义错误;
fn验证(食品:Vec)->结果{
让mut discriminants=HashSet::new();
食物中的食物{
如果!判别式。插入(判别式(&食物)){
返回错误(CustomError);
}
}
好(())
}