Reversing a string in Rust

2019-04-20 14:16发布

What is wrong with this:

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

I get an error like this:

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

What is the correct way to do this?

标签: rust
2条回答
该账号已被封号
2楼-- · 2019-04-20 14:31

Since, as @DK. suggested, .graphemes() isn't available on &str in stable, you might as well just do what @huon suggested in the comments:

fn main() {
    let foo = "palimpsest";
    println!("{}", foo.chars().rev().collect::<String>());
}
查看更多
Bombasti
3楼-- · 2019-04-20 14:40

The first, and most fundamental, problem is that this isn't how you reverse a Unicode string. You are reversing the order of the code points, where you want to reverse the order of graphemes. There may be other issues with this that I'm not aware of. Text is hard.

The second issue is pointed out by the compiler: you are trying to compare a string literal to a char iterator. chars and rev don't produce new strings, they produce lazy sequences, as with iterators in general. The following works:

/*!
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()
        // flat_map takes each element of an iterator, turns that element into
        // a new iterator, then outputs the elements of these sub-iterators as
        // one long chain.  In this case, we're turning each grapheme cluster
        // into an Iterator of code points, then yielding all those code points.
        // That is, this is now an Iterator of chars from the reversed grapheme
        // clusters.
        .flat_map(|g| g.chars())
        // Collect all the chars into a new owned String.
        .collect();

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

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

Note that graphemes used to be in the standard library as an unstable method, so the above will break with sufficiently old versions of Rust. In that case, you need to use UnicodeSegmentation::graphemes(s, true) instead.

查看更多
登录 后发表回答