在 Rust 中反转字符串

66

这里有什么问题:

fn main() {
    let word: &str = "lowks";
    assert_eq!(word.chars().rev(), "skwol");
}

我遇到了这样的错误:

error[E0369]: binary operation `==` cannot be applied to type `std::iter::Rev<std::str::Chars<'_>>`
 --> src/main.rs:4:5
  |
4 |     assert_eq!(word.chars().rev(), "skwol");
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: an implementation of `std::cmp::PartialEq` might be missing for `std::iter::Rev<std::str::Chars<'_>>`
  = note: this error originates in a macro outside of the current crate

如何正确地执行此操作?

3个回答

99

正如@DK所建议的那样,.graphemes()在stable版本中无法在&str上使用,因此您可以按照@huon在评论中建议的做法。

fn main() {
    let foo = "palimpsest";
    println!("{}", foo.chars().rev().collect::<String>());
}

10
正如 DK. 的回答中提到的那样,这可能是错误的。例如,它在"Åström"方面完全失败了。 - Shepmaster
3
@Shepmaster,看起来在上面的Playground链接中使用chars()函数可以使用"Åström"。至少我看到的输出是m̈orts̊A。不确定稳定版是否最近更新以支持此功能。 - MilesF
2
@MilesF Ås vs s̊A / öm vs m̈o - Shepmaster
不错。在游乐场输出窗口中,事物似乎更加对齐。https://i.ibb.co/31rNjXT/chars.png - MilesF
rev 不能再被调用于 Chars 上了吗? - theonlygusti

68

首先,也是最根本的问题是,这不是如何翻转 Unicode 字符串的方法。你正在翻转代码点的顺序,而你想要翻转 字形 的顺序。我可能还没有意识到其他问题。文本很难。

第二个问题是编译器指出的:你试图将字符串文字与 char 迭代器进行比较。 charsrev 不会产生新的字符串,它们会像一般的迭代器一样生成惰性序列。可以通过以下方式解决

/*!
Add the following to your `Cargo.toml`:

```cargo
[dependencies]
unicode-segmentation = "0.1.2"
```
*/
extern crate unicode_segmentation;
use unicode_segmentation::UnicodeSegmentation;

fn main() {
    let word: &str = "loẅks";
    let drow: String = word
        // Split the string into an Iterator of &strs, where each element is an
        // extended grapheme cluster.
        .graphemes(true)
        // Reverse the order of the grapheme iterator.
        .rev()
        // Collect all the chars into a new owned String.
        .collect();

    assert_eq!(drow, "skẅol");

    // Print it out to be sure.
    println!("drow = `{}`", drow);
}

请注意,graphemes曾经作为不稳定的方法存在于标准库中,因此在Rust旧版本中上述方法将会出问题。在这种情况下,您需要使用UnicodeSegmentation::graphemes(s, true)代替。


22
我认为你可以只使用.rev().collect(),因为String实现了FromIterator<&str>。另外,就算这么说可能不太重要,我认为真正最基本的问题是对迭代器、字符串和类型的理解出现了误解(可以理解,很多语言并不是那么“严谨”),而不是Unicode正确性的一些细微问题。 - huon
1
@dbaupp:我认为与实现语言无关的问题比特定于某种语言的问题更加基本。 :D 但是知道String支持FromIterator<&str>还是很好的。有点遗憾的是它不会预先分配存储空间,但你并不总能得到你想要的... - DK.
1
嗯,这个问题是关于为什么某段代码在特定语言中无法编译,而不是为什么它会产生意外的输出(即算法与语言无关的问题),因此问题本身的根本问题是 Rust 特定的类型错误。当然,提到 Unicode 很困难也是很好的。 - huon

0

如果您只涉及ASCII字符,可以使用不稳定的reverse函数对切片进行就地反转。

它做的事情类似于这样:

fn main() {
    let mut slice = *b"lowks";
    let end = slice.len() - 1;
    for i in 0..end / 2 {
        slice.swap(i, end - i);
    }
    assert_eq!(std::str::from_utf8(&slice).unwrap(), "skwol");
}

游乐场


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接