rust - 改变 HashMap> 中的向量元素

我已经解决了一个我看到的问题 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/

相关文章:

java - 在 JPA 存储库中连接两个表

javascript - TypeScript 和文件上传类型

r - 从类(class)列表中查找当前事件条目

algorithm - 如果一个节点等于二叉搜索树中的父节点,我们将它放在哪一边

rust - 为什么 Rust 中原始类型之间没有隐式类型转换(强制转换)

javascript - Js 文件作为 cypress 中的夹具未加载

javascript - 两个 TX 的双哈希

postgresql - 使用 SymmetricDS 的主动-主动 PostgreSQL 配置

r - 使用ggsave时遇到 "Error: $ operator is invalid for

flutter - 未处理的异常 : type '_InternalLinkedHashMap