Доступ к последнему элементу Vec или среза в Rust
Проблема с методом 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 ответ(ов)
Вопрос стал очевиден сразу после его публикации. Вот исправленный код:
fn top(&mut self) -> Option<&f64> {
match self.len() {
0 => None,
n => Some(&self[n - 1])
}
}
То есть, проблема заключалась не в usize
, а в возвращаемом типе функции top()
.
В последнем элементе в 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
мы создаем экземпляр стека, добавляем в него несколько чисел и выводим верхний элемент.
Почему println! не работает в юнит-тестах Rust?
Что означает "Sized не реализован"?
Лучшие практики использования постоянных хеш-карт в Rust
Как объявить вектор-участник того же класса?
Как проще всего преобразовать строку в верхний регистр в Rust?