从字符串中获取单个字符

XAM*_*cky 37 string rust

我想得到一个第一个角色std::str.该方法char_at()目前是不稳定的,如slice_charsstd::string::String.

我目前唯一提出的选择如下.

let text = "hello world!";
let char_vec:Vec<char> = text.chars().collect();
let ch = char_vec[0];
Run Code Online (Sandbox Code Playgroud)

但这对于获得单个字符似乎过分,而不是使用向量的其余部分.

Ste*_*nik 60

UTF-8没有定义"字符"是什么,所以它取决于你想要的.在这种情况下,chars是Unicode标量值,因此a的第char一个&str将在1到4个字节之间.

如果你只想要第一个char,那么不要收集到一个Vec<char>,只需使用迭代器:

let text = "hello world!";
let ch = text.chars().next().unwrap();
Run Code Online (Sandbox Code Playgroud)

  • 您可能还想看看您是否真的想要第一个_grapheme_. (3认同)
  • @delnan:我认为实际使用`char_at`有点危险,因为索引可能是*代码单元. (3认同)
  • @delnan:是的,无论如何,代码点索引在O(1)中都不起作用.然而,当有人要求第n个字符时,他们可能会要求第n个代码点或第n个字形集群,但它们不太可能要求第n个字节. (3认同)
  • 这给出了第 n 个代码单元,但 char_at 给出了从字节 n 开始的代码单元。后者更有用,因为大多数字符串操作处理字节索引。这相当于`char_at`(也是常量时间):`text[i..].chars().next().unwrap()` (2认同)

Dar*_*ter 10

If you only want to test for it, you can use starts_with():

"rust".starts_with('r')
"rust".starts_with(|c| c == 'r')
Run Code Online (Sandbox Code Playgroud)

  • @MikeB 第一个将第一个字符与常量进行比较 - 所以你肯定需要事先知道你在寻找什么。第二个将其传递到可以对其采取行动的闭包。 (2认同)

小智 6

我编写了一个返回 a 的头部&str和其余部分的函数:

fn car_cdr(s: &str) -> (&str, &str) {
    for i in 1..5 {
        let r = s.get(0..i);
        match r {
            Some(x) => return (x, &s[i..]),
            None => (),
        }
    }

    (&s[0..0], s)
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

let (first_char, remainder) = car_cdr("test");
println!("first char: {}\nremainder: {}", first_char, remainder);
Run Code Online (Sandbox Code Playgroud)

输出看起来像:

fn car_cdr(s: &str) -> (&str, &str) {
    for i in 1..5 {
        let r = s.get(0..i);
        match r {
            Some(x) => return (x, &s[i..]),
            None => (),
        }
    }

    (&s[0..0], s)
}
Run Code Online (Sandbox Code Playgroud)

它适用于超过 1 个字节的字符。

  • @Sean 你现在可能知道了,但是 chars() 返回一个迭代器。迭代器是惰性计算的(并且零成本,意味着编译器在编译时重写它们),因此它实际上应该非常高效。 (6认同)
  • 似乎[这样会更简单](https://play.rust-lang.org/?gist=c1a86a9de2b277ce571e5186eae85b7c&amp;version=stable)。 (3认同)