impl push(self, item: T) для структуры с 2 векторами

#rust #traits #borrowing

#Ржавчина #Трейты #заимствование

Вопрос:

Я пытался внедрить толчок для этой структуры:

 struct StackMin<T: std::cmp::Ord>
{
    stack : Vec<T>,
    min : Vec<T>
}
 

вот так:

 fn push(amp;mut self, item: T) {
    let l = self.stack.len();
    let x: T;
    match l {
        0 => println!("There is nothing in the stack."),
        n => {
            if item <= self.stack[l - 1] {
                self.stack.push(item); //item moved here
                self.min.push(item); // so I can't use it again here
            } else {
                self.stack.push(item);
            }
        }
    }
}
 

Проблема в том, что элемент перемещается вместе с первым Vec<T>::push , поэтому я не могу использовать его сразу при втором вызове push(). Я думал о создании переменной let a = amp;item и использовании ее во втором вызове, но для push требуется «T», а не «amp;T».

Кроме того, если я попытаюсь это сделать a=self.stack[l-1] , это будет ошибкой, потому T что тип не имеет Copy / Clone черт.

ПОСЛЕДУЮЩЕЕ РЕДАКТИРОВАНИЕ: мне также нужно напечатать последнее значение из минимального вектора. Но у него нет std ::fmt ::Display , и я не думаю, что это может быть impl !? Есть какие-нибудь идеи?

Как бы вы подошли к этому?

Комментарии:

1. Предполагая, что вам действительно нужны два вектора T, вы мало что можете здесь сделать. Вещь не может быть в двух местах одновременно. Либо имейте один (или оба) хранилища векторов amp;T (на этом этапе вам придется иметь дело со временем жизни), либо дополнительно ограничьте T для клонирования или копирования.

2. почему бы не ограничить Clone ?

3. Купить как мне приступить к созданию признаков клонирования / копирования для типа <T>?

4. Просто <T: std::cmp::Ord Clone> ?

5. Это просто невозможно реализовать с учетом этих ограничений, что говорит о том, что это проблема XY . Сделайте небольшую резервную копию: что вы пытаетесь сделать?

Ответ №1:

Предполагая, что вы можете изменить внутренние значения структуры StackMin , но не требования к признакам, вы могли бы сделать что-то вроде этого:

 struct MinStack<T: std::cmp::Ord> {
    // T is the data you want to store
    // and usize points to the smallest T
    inner: Vec<(T, usize)>
}

impl<T: std::cmp::Ord> MinStack<T> {
    fn push(amp;mut self, val: T) {
        let min_index = self.inner.last()
            // get last min value and its index
            .map(|(_, index)| (amp;self.inner[*index].0, index))
            // check if it is smaller then the current value
            .and_then(|(prev_min, min_index)| 
                (prev_min < amp;val).then(|| *min_index)
            )
            // if not smaller or does not exist
            // set it to the current index
            .unwrap_or(self.inner.len());

        self.inner.push((val, min_index));
    }
}
 

Вот полная реализация игровой площадки minStack challenge Rust.
Дайте мне знать, если я должен что-то уточнить в приведенном выше коде.

Документы для используемых методов: