【问题标题】:Modify string inside a Vec<&str> in rust and general ownership confusion在 rust 和一般所有权混淆中修改 Vec<&str> 中的字符串
【发布时间】:2021-06-28 00:52:57
【问题描述】:

我是 Rust 的新手,我很难理解所有权概念。我有一个字符串,其中包含具有特定模式的子字符串,例如“alice [bob] charlie [dave]”,并且我正在尝试获取看起来像(“john”,“dave”)的字符串向量)。我的第一次尝试是使用带有非捕获组的正则表达式,但我无法让它发挥作用,因为我不太了解 rust:

let re = Regex::new(r"(?:\[)([a-zA-Z]+)(?:])").unwrap();
let mut answer: Vec<&str> = re.captures_iter((&text)).map(|capGroup| &*String::from(&capGroup[1])).collect();

但我可以像这样收集它们:

let re = Regex::new(r"\[[a-zA-Z0-9_]+]").unwrap();
let mut answer: Vec<&str> = re.find_iter((&text)).map(|mtc| mtc.as_str()).collect();

这个问题是它给我留下了(“[bob]”,“[dave]”),而且我在修剪字符串的第一个和最后几个字符方面也没有成功。事实上,我什至不明白这里的迭代是如何工作的,因为当我尝试这样做时:

 let mut it = answer.iter();
 for name in &mut it{
      ...

我最终得到的名称是 &amp;&amp;str 类型,而不是我预期的 &amp;str。 所以我的问题是:

  • 如何以惯用的方式在第一个示例中尝试使用 rust 中的捕获组?我觉得我已经接近将某些东西应用于所有捕获并收集到 vec 中的标记,但有些东西正在逃避我。
  • 给定Vec&lt;&amp;str&gt;,如何修改其中的字符串?我在这里缺少什么?
  • 当我这样做时,为什么我的迭代项类型为 &amp;&amp;str
  • 有没有更好的方法来实现这一点?

【问题讨论】:

    标签: regex string rust


    【解决方案1】:

    要删除"[]",您可以在正则表达式中添加一个捕获组,然后仅过滤由它捕获的匹配项:

    let text = "alice bob [charlie] dave [emily]";
    
    let re = Regex::new(r"\[([a-zA-Z0-9_]+)]").unwrap();
    let answer: Vec<&str> = re
        .captures_iter(text)
        .filter_map(|capture| capture.get(1))
        .map(|mtch| mtch.as_str())
        .collect();
    
    println!("{:?}", answer); // ["charlie", "emily"]
    

    Capture::get 返回 Option,因此您可以将其与 filter_map 一起使用以过滤掉所有未在此处捕获的匹配项,因为 capture.get(1) 将为这些返回 None


    要回答另一个问题,迭代器中的项目之所以为&amp;&amp;str 类型是因为向量包含&amp;str,但您正在迭代对向量的引用,所以一切都是双重借用的。

    这些借用了向量,因此您正在迭代&amp;&amp;str

    for item in &answer {
        // item is &&str
    }
    
    // which is syntactic sugar for:
    for item in (&answer).into_iter() {
        // item is &&str
    }
    
    for item in answer.iter() {
        // item is &&str
    }
    

    这会迭代&amp;str,但移动向量,所以你不能再次使用它:

    for item in answer {
        // item is &str
    }
    
    // is sugar for:
    for item in answer.into_iter() {
        // item is &str
    }
    

    您可以通过复制切片来迭代 &amp;str 而无需移动向量。这很便宜,因为只复制了指针:

    for item in answer.iter().copied() {
        // item is &str
    }
    

    拥有&amp;&amp;str 而不是&amp;str 几乎从来都不是问题。 &amp;str 的方法仍然可以在 &amp;&amp;str 上调用,如果需要,您可以随时使用 * 取消引用它。

    【讨论】:

      【解决方案2】:

      只是一些一般信息:在 rust 中,&amp;str 只是对字符串切片的引用,这意味着没有指向变量的所有权。因此,在您的示例let mut answer: Vec&lt;&amp;str&gt; 中,可变变量answer 不拥有Vec 中的任何切片。由于 &amp;str 是不可变的 str 引用,因此您需要所有权才能改变它们。因此,您可以使用 .to_owned() 函数将它们转换为 String 对象。 String slices(&amp;str) 和 Strings(String) 在 rust 上是完全不同的。这是一个很好的解释:What are the differences between Rust's `String` and `str`?

      1. 对于您的问题“当我这样做时,为什么我的迭代项是 &&str 类型的?”,您正在引用(&amp;)对字符串切片(&amp;str)的引用。

      2. 对于您的问题“给定 Vec,我如何修改其中的字符串?我在这里缺少什么?”解决此问题的一种方法是使用 String 结构。

      【讨论】:

        猜你喜欢
        • 2018-08-08
        • 1970-01-01
        • 1970-01-01
        • 2022-01-20
        • 1970-01-01
        • 2015-10-06
        • 2020-05-30
        • 2010-11-02
        • 2017-05-16
        相关资源
        最近更新 更多