How do I compare a vector against a reversed version of itself?

孤者浪人 提交于 2020-01-02 05:20:53

问题


Why won't this compile?

fn isPalindrome<T>(v: Vec<T>) -> bool {
  return v.reverse() == v;
}

I get

error[E0308]: mismatched types
 --> src/main.rs:2:25
  |
2 |   return v.reverse() == v;
  |                         ^ expected (), found struct `std::vec::Vec`
  |
  = note: expected type `()`
             found type `std::vec::Vec<T>`

回答1:


Read up on the documentation for the function you are using:

Reverse the order of elements in a slice, in place.

Or check the function signature:

fn reverse(&mut self)

The return value of the method is the unit type, an empty tuple (). You can't compare that against a vector.


Stylistically, Rust uses 4 space indents, snake_case identifiers for functions and variables, and has an implicit return at the end of blocks. You should adjust to these conventions in a new language.

Additionally, you should take a &[T] instead of a Vec<T> if you are not adding items to the vector.

To solve your problem, we will use iterators to compare the slice. You can get forward and backward iterators of a slide, which requires a very small amount of space compared to reversing the entire array. Iterator::eq allows you to do the comparison succinctly.

You also need to state that the T is comparable against itself, which requires Eq or PartialEq.

fn is_palindrome<T>(v: &[T]) -> bool
where
    T: Eq,
{
    v.iter().eq(v.iter().rev())
}

fn main() {
    println!("{}", is_palindrome(&[1, 2, 3]));
    println!("{}", is_palindrome(&[1, 2, 1]));
}

If you wanted to do the less-space efficient version, you have to allocate a new vector yourself:

fn is_palindrome<T>(v: &[T]) -> bool
where
    T: Eq + Clone,
{
    let mut reverse = v.to_vec();
    reverse.reverse();
    reverse == v
}

fn main() {
    println!("{}", is_palindrome(&[1, 2, 3]));
    println!("{}", is_palindrome(&[1, 2, 1]));
}

Note that we are now also required to Clone the items in the vector, so we add that trait bound to the method.




回答2:


Since you only need to look at the front half and back half, you can use the DoubleEndedIterator trait (methods .next() and .next_back()) to look at pairs of front and back elements this way:

/// Determine if an iterable equals itself reversed
fn is_palindrome<I>(iterable: I) -> bool
where
    I: IntoIterator,
    I::Item: PartialEq,
    I::IntoIter: DoubleEndedIterator,
{
    let mut iter = iterable.into_iter();
    while let (Some(front), Some(back)) = (iter.next(), iter.next_back()) {
        if front != back {
            return false;
        }
    }

    true
}

(run in playground)

This version is a bit more general, since it supports any iterable that is double ended, for example slice and chars iterators.

It only examines each element once, and it automatically skips the remaining middle element if the iterator was of odd length.



来源:https://stackoverflow.com/questions/33348032/how-do-i-compare-a-vector-against-a-reversed-version-of-itself

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!