【问题标题】:How to get the last character of a &str?如何获取 &str 的最后一个字符?
【发布时间】:2018-07-16 11:25:52
【问题描述】:

在 Python 中,这将是 final_char = mystring[-1]。我怎样才能在 Rust 中做同样的事情?

我试过了

mystring[mystring.len() - 1]

但我收到错误 the type 'str' cannot be indexed by 'usize'

【问题讨论】:

  • 你的意思是unicode代码点的字符?
  • @BB 您或许应该回答的问题(主要是为您自己)是café 的最后一个“字符”是 还是´。如果它应该是é,你想通过字形而不是chars 进行迭代。
  • @BB 我认为您正在向后看。文本处理是困难,因为人类语言很复杂,将它们编码到计算机中也很复杂。 Rust 有一小部分意见(例如,字符串是 UTF-8),但除此之外必须不干涉以允许程序员为他们的案例构建他们需要的正确抽象。正如其他人所提到的,将字符串视为字符包最终是不正确的,因为在我们的全球世界中,“字符”的定义并不明确。
  • @BB Python 3 在正确的 Unicode 处理方面取得了长足的进步,但它仍然没有提供使用字素的简单方法——Rust(使用unicode-segmentation crate)实际上在这方面更好看待。如果您将"café"[-1] 复制并粘贴到您的Python 解释器中,它可能不会给您"é"

标签: string rust


【解决方案1】:

正如@Boiethios 提到的

let last_ch = mystring.chars().last().unwrap();

或者

let last_ch = codes.chars().rev().nth(0).unwrap();

我宁愿拥有(这有多难!?)

let last_ch = codes.chars(-1); // Not implemented as rustc 1.56.1

【讨论】:

    【解决方案2】:

    一种选择是使用slices。这是一个例子:

    let len = my_str.len();
    let final_str = &my_str[len-1..];
    

    这将返回从位置len-1 到字符串末尾的字符串切片。也就是说,你的字符串的最后一个byte。如果您的字符串仅包含 ASCII 值,那么您将获得字符串的最后一个字符。

    这只适用于 ASCII 值的原因是它们只需要一个字节的存储空间。其他任何事情,Rust 都可能在运行时出现恐慌。当您尝试从 2 字节字符中切出 1 字节时会发生这种情况。

    更详细的解释请看the Rust book的字符串部分。

    【讨论】:

    • 说解决方案有问题但不说明这些问题是什么会产生非常糟糕的答案。外部资源的链接很棒,但任何相关信息都需要包含在答案本身中。
    • 即字符串中包含的最终值。 — 除非您处理纯 ASCII 文本,否则这不是真的;随着时间的推移,这种说法越来越不真实。想想表情符号。
    【解决方案3】:

    这就是你获得最后一个char 的方式(可能不是你认为的“字符”):

    mystring.chars().last().unwrap();
    

    仅当您确定字符串中至少有一个字符时才使用unwrap


    警告:关于一般情况(与 Python 中的mystring[-n] 做同样的事情):UTF-8 字符串不能通过索引使用,因为索引不是 O(1)操作(Rust 中的字符串不是数组)。请阅读this了解更多信息。

    但是,如果你想像在 Python 中那样从末尾开始索引,你必须在 Rust 中这样做:

    mystring.chars().rev().nth(n - 1) // Python: mystring[-n]
    

    并检查是否有这样的字符。

    如果你错过了 Python 语法的简单性,你可以编写自己的扩展:

    trait StrExt {
        fn from_end(&self, n: usize) -> char;
    }
    
    impl<'a> StrExt for &'a str {
        fn from_end(&self, n: usize) -> char {
            self.chars().rev().nth(n).expect("Index out of range in 'from_end'")
        }
    }
    
    fn main() {
        println!("{}", "foobar".from_end(2)) // prints 'b'
    }
    

    【讨论】:

    • @erip 还没有读到本书的那部分,但感谢您的提醒!
    • @BB 还应该注意的是,这是 Rust 中的 O(n) 操作,而不是 Python 的 O(1)。您不应将字符串视为数组。
    • @DK 澄清一下,获取最后一个字符是 O(1) 操作。从任一端获取第 n 个字符是 O(n),其中 n 是索引。
    • “我的印象是不鼓励使用unwrap这是to panic! or not to panic!的问题。 unwrap 表示来自那里的任何潜在错误都是不可恢复的,不应该发生。仍然有合法的案例。
    猜你喜欢
    • 2011-07-07
    • 2011-08-17
    • 2021-09-18
    • 1970-01-01
    • 2021-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多