How to invert a `HashMap<String, MyEnum>`? (Error: "`FromIterator` not implemented for [pair]")

How to invert a `HashMap<String, MyEnum>`? (Error: "`FromIterator` not implemented for [pair]")

我试图在 Rust 中反转 HashMap<String, MyEnum>,但出现错误:

代码:

use std::collections::HashMap;

// Directive added because of this answer, which eliminated a couple of errors:
// https://github.com/rust-lang/rust/issues/22756#issuecomment-75715762
#[derive(Debug, PartialEq, Eq, Hash)]
enum MyEnum {
    Value1,
    Value2,
}

static MYMAP: HashMap<String, MyEnum> = HashMap::from([
    (String::from("value1"), MyEnum::Value1),
    (String::from("value1"), MyEnum::Value1),
]);

static MYMAP_INVERTED: HashMap<MyEnum, String> = HashMap::from([
    MYMAP.iter().map(|(k, v)| (v, k)).collect()
]);

错误:

error[E0277]: a value of type `(_, _)` cannot be built from an iterator over elements of type `(&MyEnum, &String)`
    --> src/main.rs:15:39
     |
15   |     MYMAP.iter().map(|(k, v)| (v, k)).collect()
     |                                       ^^^^^^^ value of type `(_, _)` cannot be built from `std::iter::Iterator<Item=(&MyEnum, &String)>`
     |
     = help: the trait `FromIterator<(&MyEnum, &String)>` is not implemented for `(_, _)`
note: required by a bound in `collect`

For more information about this error, try `rustc --explain E0277`.

你会如何为一对实施 FromIterator

你的方法没问题,你的类型不对。或者你有参考资料:

let my_map_inverted: HashMap<&MyEnum, &String> = my_map.iter()
    .map(|(k, v)| (v, k)).collect();

Playground

或者您 Clone 键和值:

let my_map_inverted: HashMap<MyEnum, String> = my_map.iter()
    .map(|(k, v)| (v.clone(), k.clone())).collect();

Playground

然后你还有一些其他问题,比如有些调用不能在静态上下文中使用,你可以使用once_cell

use std::collections::HashMap;
use once_cell::sync::Lazy; // 1.10.0;

// Directive added because of this answer, which eliminated a couple of errors:
// https://github.com/rust-lang/rust/issues/22756#issuecomment-75715762
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
enum MyEnum {
    Value1,
    Value2,
}

static MYMAP: Lazy<HashMap<String, MyEnum>> = Lazy::new(
    || HashMap::from_iter([
        (String::from("value1"), MyEnum::Value1),
        (String::from("value1"), MyEnum::Value1),
]));

static MYMAP_INVERTED: Lazy<HashMap<MyEnum, String>> = Lazy::new(
    || HashMap::from_iter(MYMAP.iter().map(|(k, v)| (v.clone(), k.clone()))
));

Playground

要交换键和值,最好使用 from_iter 构造函数,因为 from 不能接受 Vec,而 collect 不确定要做什么按照现在的方式去做。执行此操作的代码如下所示,但您不能在静态上下文中使用类似的方法,因此需要重构:

let MYMAP_INVERTED: HashMap<MyEnum, String> = HashMap::from_iter(
    MYMAP.iter().map(|(k, v)| (*v, k.clone()))
);

*vk.clone() 是必需的,因为 map 将 return 引用数据。

至于静态问题,您最好的选择是使用标准库中的 lazy_static crate or a SyncLazy