我正在try 制作不同类型的HashMap.我不想为特定的数据类型创建两个不同的HashMap.

我的代码如下:

use std::collections::HashMap;

#[derive(Debug)]
enum DataTypes {
    String(String),
    Bool(bool),
}

fn get_hashmap() -> Result<HashMap<String, DataTypes>, ()>{
    let data = HashMap::from([
        ("password".to_string(), DataTypes::String("password".to_string())),
        ("username".to_string(), DataTypes::String("Fun username".to_string())),
        ("is_blocked".to_string(), DataTypes::Bool(true)),
        ("is_confirmed".to_string(), DataTypes::Bool(false)),
    ]);
    Ok(data)
}
fn main() {
    let data = get_hashmap().unwrap();
    let keys = data.keys();
    println!("Keys: {:?}", &keys);
    for key in keys {
        let result: Option<T> = match data.get(key).unwrap() {
            DataTypes::Bool(value) => Some(value),
            DataTypes::String(value) => Some(value),
            _ => panic!("Error!"),
        };
        println!("Result of matching: {:?}", &result);
    }
}

就像你可以看到的,我正在试图操纵Enums来获得他们的价值.但我有一些数据类型的问题. 我对此的解决方案是将结果包装到某个 struct .但主要问题仍然没有得到解决.

所以我想使Option类中的匹配结果可用来使用UnWrap(). 但我不知道如何才能正确地做到这一点.

我有两个问题:

  1. 我能做得更好吗?
  2. 我如何将let Result:选项包装到工作状态?

推荐答案

以下是一些反馈:

  • 如果您已经处理了所有选项,则不要包括_个默认匹配大小写.它将隐藏future 的错误.
  • 如果每个成员都只是一种数据类型,则不要将变量命名为DataTypes.把它命名为DataType.
  • result必须是一个特定的类型.枚举的全部意义在于您可以分别处理不同的值,因此将它们组合在result类型中是没有意义的.当然,can保留resultDataType对象,并为其实现Debug/Display,这就是我将在重新编写的代码中如何做到这一点.
  • 虽然您先can查询键,然后在循环中再次查询值,但这相当慢.您可以立即迭代键-值对.这样,您就避免了许多unwrap(),这使得您的代码更不容易出错.
use std::collections::HashMap;

#[derive(Debug)]
enum DataType {
    String(String),
    Bool(bool),
}

fn get_hashmap() -> Result<HashMap<String, DataType>, ()> {
    let data = HashMap::from([
        (
            "password".to_string(),
            DataType::String("password".to_string()),
        ),
        (
            "username".to_string(),
            DataType::String("Fun username".to_string()),
        ),
        ("is_blocked".to_string(), DataType::Bool(true)),
        ("is_confirmed".to_string(), DataType::Bool(false)),
    ]);
    Ok(data)
}
fn main() {
    let data = get_hashmap().unwrap();
    for (key, value) in data {
        println!("{}: {:?}", key, value);

        match value {
            DataType::Bool(value) => {
                println!("\tValue was a bool: {}", value);
                // do something if the value is a bool
            }
            DataType::String(value) => {
                println!("\tValue was a string: {}", value);
                // do something if the value is a string,
            } /*
               * Don't include a default case. That way the compiler
               * will remind you to handle additional enum entries if
               * you add them in the future.
               * Adding a default case is only a good practice in languages
               * where matching is not exhaustive.
               */
        };
    }
}
username: String("Fun username")
        Value was a string: Fun username
is_confirmed: Bool(false)
        Value was a bool: false
is_blocked: Bool(true)
        Value was a bool: true
password: String("password")
        Value was a string: password

不过,不要担心,您不需要在使用此枚举的任何地方都使用match,否则与两个单独的哈希图相比,您不会获得太多好处.相反,您可以为所有枚举条目定义共享功能,并隐藏其中的match.就像这样:

use std::collections::HashMap;

#[derive(Debug)]
enum DataType {
    String(String),
    Bool(bool),
}

impl DataType {
    fn do_something(&self) {
        match self {
            DataType::Bool(value) => {
                println!("\tDo something with boolean '{}'!", value);
            }
            DataType::String(value) => {
                println!("\tDo something with string {:?}!", value);
            }
        };
    }
}

fn get_hashmap() -> Result<HashMap<String, DataType>, ()> {
    let data = HashMap::from([
        (
            "password".to_string(),
            DataType::String("password".to_string()),
        ),
        (
            "username".to_string(),
            DataType::String("Fun username".to_string()),
        ),
        ("is_blocked".to_string(), DataType::Bool(true)),
        ("is_confirmed".to_string(), DataType::Bool(false)),
    ]);
    Ok(data)
}

fn main() {
    let data = get_hashmap().unwrap();
    for (key, value) in data {
        println!("{}: {:?}", key, value);
        value.do_something();
    }
}
is_confirmed: Bool(false)
        Do something with boolean 'false'!
password: String("password")
        Do something with string "password"!
is_blocked: Bool(true)
        Do something with boolean 'true'!
username: String("Fun username")
        Do something with string "Fun username"!

如果您的目标是将序列化/反序列化添加到您的 struct 中(就像您在这里手动实现的那样),让我提示您接近serde,它已经免费处理了大部分序列化.

如本例所示(它可能是也可能不是您的 struct 的样子),它将您的 struct 序列化到JSON和从JSON序列化:

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct User {
    username: String,
    password: String,
    is_blocked: bool,
    is_confirmed: bool,
}

fn main() {
    let user = User {
        username: "Fun username".to_string(),
        password: "password".to_string(),
        is_blocked: true,
        is_confirmed: false,
    };

    let user_serialized = serde_json::to_string(&user).unwrap();
    println!("Serialized: {}", user_serialized);

    let user_deserialized: User = serde_json::from_str(&user_serialized).unwrap();
    println!("Name: {}", user_deserialized.username);
}
Serialized: {"username":"Fun username","password":"password","is_blocked":true,"is_confirmed":false}
Name: Fun username

Rust相关问答推荐

Tauri tauri—apps/plugin—store + zustand

如何从使用mockall模拟的方法中返回self?

收集RangeInclusive T到Vec T<><>

如何装箱生命周期相关联的两个对象?

是否可以使用Rust宏来构建元组的项?

如果死 struct 实现了/派生了一些特征,为什么Rust会停止检测它们?

在Rust中,Box:ed struct 与普通 struct 在删除顺序上有区别吗?

这个不安全的 Rust 代码有什么问题,所以它可以在 Windows 上运行,但不能在 Ubuntu 上运行?

当我try 使用 SKI 演算中的S I I实现递归时,为什么 Rust 会失败?

为什么某些类型参数仅在特征边界中使用的代码在没有 PhantomData 的情况下进行编译?

OpenGL 如何同时渲染无纹理的四边形和有纹理的四边形

注释闭包参数强调使用高阶排定特征界限

trait 对象指针的生命周期

如何在 Emacs Elisp 中获得类似格式化的 LSP?

LinkedList::drain_filter::drop 中 DropGuard 的作用是什么?

为什么 &i32 可以与 Rust 中的 &&i32 进行比较?

在空表达式语句中移动的值

相交着色器从 SSBO 中读取零

tokio async rust 的 yield 是什么意思?

为什么 std::iter::Peekable::peek 可变地borrow self 参数?