我对 Rust 还比较陌生。我想编写一个函数,该函数将根据给定的闭包从集合创建 HashMap,该闭包从值生成键,例如
[derive(Debug)]
struct Foo {
id: u32,
name: String,
}
let foos = vec![
Foo { id: 1, name: "Bill".to_string() },
Foo { id: 2, name: "Mary".to_string() },
];
println!("{:?}", foos);
println!("{:?}", map_by(foos.iter(), |f| f.id)); // borrow the Foos
println!("{:?}", map_by(foos.iter(), |f| &f.name)); // borrow
println!("{:?}", map_by(foos.iter(), |f| f.name.as_str())); // borrow
println!("{:?}", map_by(foos, |f| f.id)); // consume the Foos
Run Code Online (Sandbox Code Playgroud)
我写了这个,它适用于上述用途:
fn map_by<I,K,V>(iterable: I, f: impl Fn(&V) -> K) -> HashMap<K,V>
where I: IntoIterator<Item = V>,
K: Eq + Hash
{
iterable.into_iter().map(|v| (f(&v), v)).collect()
}
[Foo { id: 1, name: "Bill" }, Foo { id: 2, name: "Mary" }]
{1: Foo { id: 1, name: "Bill" }, 2: Foo { id: 2, name: "Mary" }}
{"Bill": Foo { id: 1, name: "Bill" }, "Mary": Foo { id: 2, name: "Mary" }}
{"Bill": Foo { id: 1, name: "Bill" }, "Mary": Foo { id: 2, name: "Mary" }}
{2: Foo { id: 2, name: "Mary" }, 1: Foo { id: 1, name: "Bill" }}
Run Code Online (Sandbox Code Playgroud)
伟大的!但是当我让 HashMap 拥有键引用它们的值时,它不起作用:
println!("{:?}", map_by(foos, |f| f.name.as_str()));
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
Run Code Online (Sandbox Code Playgroud)
不幸的是,错误信息融化了我的大脑。我尝试指定键和值具有相同的生命周期,但这没有帮助。 这是在操场上。编译器试图告诉我什么,我做错了什么?当然,如果我们借用这些值时这可以起作用,那么当我们拥有它们时它也可以起作用。
当然,如果我们借用这些值时这可以起作用,那么当我们拥有它们时它也可以起作用。
不会。当 AHashMap需要调整自身大小以容纳新条目时,它会在内存中移动条目。如果键借用了值,并且条目被移动,则值的地址将发生变化,并且键中的引用将不再有效。
有关详细信息,请参阅为什么不能在同一结构中存储值和对该值的引用?。