Страницы

Поиск по вопросам

понедельник, 22 октября 2018 г.

Проход по for i in 0..vector.len() и 'index out of bounds'

Делаю задачу для тренировки, в последнем for выскакивает ошибка о выходе за границы вектора :
thread '

' panicked at 'index out of bounds: the len is 22 but the index is 22', ../src/libcollections/vec.rs:1106*
Не могу понять, почему так происходит, в цикле for не проверяется результат len() при каждом новом проходе цикла?
fn main(){ let e = 0.005; let n = 30; let mut vector: Vec; vector = Vec::new(); for i in 0..n { let result:f32 = 1./(i as f32 + 1.).powf(2.0); vector.push( result ); } for i in 0..vector.len(){ println!("len:{:?}", vector.len()); if vector[i] < e { println!("{:?}", vector[i]); vector.remove(i); } } }
Я переделал под while и всё работает, но заводить счётчик до цикла как-то не красиво, да и i+=1; тоже, можно ли как-то это оформить посимпотичнее? Вот что получилось вместо последнего for
let mut i=0; while( i < vector.len() ){ if vector[i] < e { println!("{:?}", vector[i]); vector.remove(i); } i+=1; }


Ответ

В добавление советую внимательно прочитать документацию по Vec и Iterator. Практически всегда, когда хочется сделать for i in 0..vec.len() в расте нужно использовать итерирование по вектору напрямую или какой-то метод самого вектора или итератора от него. В частности в данном случае гораздо лучше использовать Vec::retain(), а для построения Iterator::collect() и Iterator::map()
let mut vector = (0..n).map(|i| 1./(i as f32 + 1.).powf(2.0)).collect::>(); vector.retain(|item| item >= e);
Плюс ещё в том, что если использовать библиотечные методы и итераторы, то не будет сгенерирован код для проверки выхода индекса за границы массива (bounds check), как при использовании операции индексирования []

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

Отправить комментарий