我已经解决了一个我看到的问题 example :
use std::collections::HashMap;
fn process(mut inputs: Vec<String>) -> Vec<String> {
// keep track of duplicate entries in the input Vec
let mut duplicates: HashMap<String, Vec<&mut String>> = HashMap::new();
for input in &mut inputs {
duplicates.entry(input.clone())
.or_insert_with(|| Vec::new())
.push(input);
}
// modify the input vector in place to append the number of each duplicate
for (key, instances) in duplicates {
for (i, instance) in instances.iter().enumerate() {
*instance = format!("{}_{}", instance, i);
}
}
return inputs;
}
fn main() {
println!("results: {:?}", process(vec![
String::from("test"),
String::from("another_test"),
String::from("test")
]));
}
我希望这会打印类似 results: test_0, another_test_0, test_1
的内容,但我却遇到了构建问题:
error[E0308]: mismatched types
--> src/main.rs:13:25
|
13 | *instance = format!("{}_{}", instance, i);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&mut String`, found struct `String`
|
我对 Rust 还是有点陌生,所以还没有真正在网上找到任何有用的东西。我希望我在做一些愚蠢的事情。在此先感谢您的帮助!
最佳答案
for (key, instances) in duplicates {
for (i, instance) in instances.iter().enumerate() {
*instance = format!("{}_{}", instance, i);
}
}
for (key, instances) in duplicates
调用 IntoIterator
HashMap<String, Vec<&mut String>>
上的特征, 与
type Item = (String, Vec<&mut String>);
所以 instances: Vec<&mut String>
.1 instances.iter()
然后生成对 instances
元素的引用, 所以 instance: &&mut String
.所以instance
需要取消引用两次才能访问 inputs
中的元素,不幸的是,它实际上不起作用:
error[E0594]: cannot assign to `**instance` which is behind a `&` reference
--> src/main.rs:14:13
|
13 | for (i, instance) in instances.iter().enumerate() {
| -------- help: consider changing this to be a mutable reference: `&mut &mut String`
14 | **instance = format!("{}_{}", instance, i);
| ^^^^^^^^^^ `instance` is a `&` reference, so the data it refers to cannot be written
问题是我们不允许修改 T
背后的值(value)&&mut T
.原因如下:不可变引用可以自由复制,所以可能有多个&&mut T
指向相同 &mut T
的实例, 打败 &mut
的抗锯齿属性.
因此,我们必须改变instance
的类型至 &mut &mut String
, 通过使用 mut
和 .iter_mut()
:
for (key, mut instances) in duplicates {
for (i, instance) in instances.iter_mut().enumerate() {
**instance = format!("{}_{}", instance, i);
}
}
自 key
不需要,我们可以使用 .values_mut()
,所以 instances
本身变成一个&mut
:
for instances in duplicates.values_mut() {
for (i, instance) in instances.iter_mut().enumerate() {
**instance = format!("{}_{}", instance, i);
}
}
1 我们将使用 var: type
表示var
类型为 type
.
一般来说,存储在容器中的引用(尤其是可变引用)使用起来很乏味,所以我推荐一种替代方法:(为简单起见,使用就地接口(interface))
use std::{collections::HashMap, fmt::Write};
fn process(texts: &mut Vec<String>) {
let mut counter = HashMap::<String, usize>::new();
for text in texts.iter_mut() {
let count = counter.entry(text.clone()).or_insert(0);
write!(text, "_{}", count).unwrap();
*count += 1;
}
}
( playground )
关于rust - 改变 HashMap<String, Vec<&mut String>> 中的向量元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68157806/