如何将字符串与字符串文字相匹配?

How to match a String against string literals?

提问人:Jeroen 提问时间:8/19/2014 最后编辑:vallentinJeroen 更新时间:10/26/2023 访问量:172636

问:

我试图弄清楚如何在 Rust 中匹配一个。String

我最初尝试像这样匹配,但我发现 Rust 不能隐式地从 转换为 .std::string::String&str

fn main() {
    let stringthing = String::from("c");
    match stringthing {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
    }
}

这有错误:

error[E0308]: mismatched types
 --> src/main.rs:4:9
  |
4 |         "a" => println!("0"),
  |         ^^^ expected struct `std::string::String`, found reference
  |
  = note: expected type `std::string::String`
             found type `&'static str`

然后我尝试构造新对象,因为我找不到将 a 转换为 .StringString&str

fn main() {
    let stringthing = String::from("c");
    match stringthing {
        String::from("a") => println!("0"),
        String::from("b") => println!("1"),
        String::from("c") => println!("2"),
    }
}

这给了我以下错误 3 次:

error[E0164]: `String::from` does not name a tuple variant or a tuple struct
 --> src/main.rs:4:9
  |
4 |         String::from("a") => return 0,
  |         ^^^^^^^^^^^^^^^^^ not a tuple variant or struct

如何在 Rust 中实际匹配 s?String

字符串 匹配 Rust

评论

8赞 Zorf 1/11/2020
stringthing.as_str()可能是所有答案中最直接的;我不喜欢,因为它是不必要的笼统,这可能会导致错误,而且不那么明确,并不完全清楚这将是一个简单明了的。as_refas_ref()&stras_str
0赞 Jeroen 1/11/2020
@Zorf 你是对的。答案在尚不存在时被接受。我更改了接受的答案,但感谢所有回答这个问题的人!as_str

答:

11赞 A.B. 8/19/2014 #1

编者注:此答案适用于 1.0 之前的 Rust 版本,不适用于 Rust 1.0

您可以在字符串切片上进行匹配。

match stringthing.as_slice() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

评论

3赞 Abrar Khan 12/9/2019
最好使用或,两者都没有获得所有权。.as_ref().as_str()
383赞 Tijs Maas 3/26/2015 #2

更新:像这样使用 将 转换为 :.as_str()String&str

match stringthing.as_str() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

Reason 更简洁,并强制执行更严格的类型检查。该特征是针对多种类型实现的,其行为可以针对类型进行更改,从而导致意想不到的结果。同样,如果输入参数更改了类型,则当该类型实现 trait 时,编译器不会发出问题信号。.as_str()as_refStringas_ref

文档建议也 https://doc.rust-lang.org/std/string/struct.String.html 使用,https://doc.rust-lang.org/std/primitive.str.htmlas_str

旧答案:

as_slice已弃用,您现在应该改用该特征:std::convert::AsRef

match stringthing.as_ref() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

请注意,您还必须显式处理 catch-all 情况。

评论

4赞 futtetennista 12/2/2015
使用 Rust 1.4.0 可以使用该功能。仅使用与字符串不匹配。trim()as_ref()
1赞 Gerard Sexton 9/20/2016
我认为匹配失败是因为删除了空格。这对于尊重以匹配用户输入非常有用。trim()
2赞 Masked Man 11/26/2016
这是行不通的。只有当我从 read_line 获取 String 时,它才能匹配 _。
0赞 tforgione 1/24/2018
不太了解 rust 如何管理不同类型的字符串,但它似乎适用于一个基本示例
2赞 wizzwizz4 6/18/2021
@MaskedMan读了一行。行以 结尾。 (或者更准确地说,)将为您删除它。read_line\n.trim_end()trim_end_matches('\n')
192赞 Anonymous Coward 9/26/2015 #3

你可以做这样的事情:

match &stringthing[..] {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

从 Rust 1.7.0 开始,还有一种方法:as_str

match stringthing.as_str() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}
25赞 Marco Scannadinari 1/23/2016 #4

你也可以这样做

match &stringthing as &str {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

看:

评论

1赞 amyiris 3/9/2021
这实际上与此相同,并且更短。.as_str()
5赞 Luis Octavio Lomeli Navarrete 3/25/2021
“.as_str()”实际上比“as &str”多 1 个字符?我错过了什么吗?@amyiris
2赞 jcdyer 2/11/2023
&x as &str是 10 个字符,并且是 10 个字符。相同的长度。x.as_str()
3赞 omrihhh 5/3/2020 #5

您可以尝试:

fn main() {
    let stringthing = String::from("c");
    match &*stringthing {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
        _ => println!("else")
    }
}

评论

12赞 Seth Difley 5/3/2020
如果你解释什么意味着什么和做什么,它可能会提高你的答案的有用性。&*stringthing
0赞 Kaplan 8/19/2022
String实现。因此,取消引用 to a 并被引用。根据 Rust 文档,这是一种比使用 .Deref<Target = str>stringthing*stringthingstr&*stringthing&stras_str()
1赞 Sunding Wei 9/2/2023
这对有强迫症的人有好处,而且丑陋,更好。s.as_ref()s.as_str()&*s
1赞 crimsondamask 1/21/2021 #6

您可以通过执行以下操作将 转换为:String&str

fn main() {
    let stringthing = String::from("c");
    match &stringthing[..] {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
    }
}
-2赞 rujen gelal 7/4/2022 #7

在 Strings 上使用 as_str() 获取字符串切片

fn main() {
    let stringthing = String::from("c");
    match stringthing.as_str() {
        String::from("a") => println!("0"),
        String::from("b") => println!("1"),
        String::from("c") => println!("2"),
    }
}

如果您从控制台获取输入并想对其执行匹配,请务必在 as_str() 之后调用 trim() 以从输入中删除转义字符,即“\n”。如

match stringthing.as_str().trim() {...}


评论

3赞 FreelanceConsultant 5/16/2023
这是行不通的。错误:预期的元组结构或元组变体,找到关联函数。play.rust-lang.org/......String::from
2赞 AlexaP 12/22/2022 #8

您可以使用 as_str() 方法将 String 转换为 &str,然后匹配 &str 值,如下所示:

fn main() {
    let stringthing = String::from("c");
    match stringthing.as_str() {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
        _ => println!("other"),
    }
}

或者,您可以将 String 值绑定到变量,然后像这样匹配该变量:

fn main() {
    let stringthing = String::from("c");
    match stringthing {
        ref x if x == "a" => println!("0"),
        ref x if x == "b" => println!("1"),
        ref x if x == "c" => println!("2"),
        _ => println!("other"),
    }
}

或者,您可以使用 == 运算符将 String 值与字符串文本进行比较,如下所示:

fn main() {
    let stringthing = String::from("c");
    if stringthing == "a" {
        println!("0");
    } else if stringthing == "b" {
        println!("1");
    } else if stringthing == "c" {
        println!("2");
    } else {
        println!("other");
    }
}
0赞 Ayoub Boumzebra 10/26/2023 #9

在 Rust 中,您通常不能直接在 match 语句中使用 String,因为 String 是一种动态的、堆分配的数据类型,并且在编译时将期望值与一组已知且固定的可能性相匹配。

但是,您可以在 match 语句中使用 String,方法是首先使用 as_str() 方法将其转换为 &str,或者使用带有对 String 的引用的模式匹配。

match 需要穷举和已知模式:match 表达式要求您在编译时指定所有可能的模式。字符串文本在编译时是已知的,因此您可以直接在匹配中使用它们。另一方面,String 的内容是在运行时确定的,并且可能会发生变化,因此不能直接在匹配中使用。