0

Доступ к последнему элементу Vec или среза в Rust

11

Проблема с методом top() в реализации трейта Stack

У меня есть код, который выглядит следующим образом:

trait Stack {
    fn top(&mut self) -> Option<f64>;
}

impl Stack for Vec<f64> {
    fn top(&mut self) -> Option<f64> {
        match self.pop() {
            None => None,
            Some(v) => {
                self.push(v);
                Some(v)
            }
        }
    }
}

fn main() {
    let mut stack: Vec<f64> = Vec::new();
    stack.push(5.3);
    stack.push(2.3);
    stack.push(1.3);

    match stack.top() {
        Some(v) => println!("Top of the stack: {}", v),
        None => println!("The stack is empty"),
    }
}

Сейчас метод top() изменяет состояние self, хотя, по моему мнению, это не должно быть необходимо. Очевидный способ реализации не сработал:

fn top(&mut self) -> Option<f64> {
    match self.len() {
        0 => None,
        n => self[n - 1],
    }
}

Я немного поэкспериментировал с преобразованием usize в i32 и обратно, но ни одно из решений не выглядит так коротко и читабельно, как мне хотелось бы.

Вопрос

Как я могу реализовать метод top(), который будет возвращать верхний элемент стека без изменения состояния вектора? Есть ли более элегантное решение для данной проблемы?

2 ответ(ов)

0

Вопрос стал очевиден сразу после его публикации. Вот исправленный код:

fn top(&mut self) -> Option<&f64> {
    match self.len() {
        0 => None,
        n => Some(&self[n - 1])
    }
}

То есть, проблема заключалась не в usize, а в возвращаемом типе функции top().

0

В последнем элементе в Vec можно получить доступ, используя сопоставление с образцом по его срезу. Этот синтаксис имеет преимущество в том, что предотвращает ошибки, связанные с выходом за пределы массива:

trait Stack {
    fn top(&self) -> Option<&f64>;
}

impl Stack for Vec<f64> {
    fn top(&self) -> Option<&f64> {
        match &self[..] {
            [] => None,
            [.., n] => Some(n),
        }
    }
}

fn main() {
    let mut stack: Vec<f64> = Vec::new();
    stack.push(5.3);
    stack.push(2.3);
    stack.push(1.3);

    match stack.top() {
        Some(v) => println!("Верхушка стека: {}", v),
        None => println!("Стек пуст"),
    }
}

В этом коде мы определяем трейт Stack, который содержит метод top, возвращающий верхний элемент стека в виде Option<&f64>. Затем мы реализуем этот трейт для Vec<f64>, используя сопоставление с образцом для извлечения последнего элемента. Если стек пуст, вернется None, в противном случае - Some(n), где n - последний элемент. В main мы создаем экземпляр стека, добавляем в него несколько чисел и выводим верхний элемент.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь