Я пытаюсь сохранить серию записей внутри Vec. Позже мне нужно повторно обработать через Vec, чтобы заполнить некоторую информацию в каждой записи о следующей записи. Минимальный пример будет примерно таким:
struct Entry {
curr: i32,
next: Option<i32>
}
struct History {
entries: Vec<Entry>
}
где я хотел бы заполнить поля next
значением curr
следующих записей. Для этого я хочу использовать функцию tuple_windows
из Itertools для изменяемого итератора. Я ожидаю, что смогу написать такую функцию:
impl History {
fn fill_next_with_itertools(&mut self) {
for (a, b) in self.entries.iter_mut().tuple_windows() {
a.next = Some(b.curr);
}
}
}
Однако он отказывается компилироваться, потому что тип итератора Item
, &mut Entry
, не является Clone
, который требуется для функции tuple_windows
. Я понимаю, что есть способ перебрать список, используя такие индексы:
fn fill_next_with_index(&mut self) {
for i in 0..(self.entries.len()-1) {
self.entries[i].next = Some(self.entries[i+1].curr);
}
}
Но я считаю подход itertools более естественным и элегантным. Каковы наилучшие способы достижения того же эффекта?
Из документации : tuple_window
клонирует элементы итератора, чтобы они могли быть частью последовательных окон, что делает его наиболее подходящим для итераторов ссылок и других значений, которые дешево копировать.
Это означает, что если бы вы реализовали его с элементами &mut
, то у вас было бы несколько изменяемых ссылок на одно и то же, поведение которого не определено.
Если вам все еще нужен общий, изменяемый доступ, вам придется обернуть его в Rc<RefCell<T>>
, Arc<Mutex<T>>
или что-то подобное:
fn fill_next_with_itertools(&mut self) {
for (a, b) in self.entries.iter_mut().map(RefCell::new).map(Rc::new).tuple_windows() {
a.borrow_mut().next = Some(b.borrow().curr);
}
}