Как перебирать массив целых чисел?

Что я могу сделать, чтобы перебрать массив целых чисел в Rust?

fn main () {

    let mut array: Vec<i64> = vec![2];

    for k in range(3, 13195) {
        for p in array.iter() {
           if (k % p != 0) {array.push(p)};
        }        
    }
}

Выдает ошибку компилятора:

rustc "Task2_minimalcode.rs" (в Verzeichnis: C: \ Users \ XXX \ Documents \ Rust - Project Euler)

Task2_minimalcode.rs:7:14: 7:15 ошибка: несовпадающие типы: ожидается _, найдено &i64 (ожидаемая интегральная переменная, найдено & -ptr) [E0308] Task2_minimalcode.rs:7 if (k% p! = 0) {array .push (p)};
^ Task2_minimalcode.rs:7:34: 7:35 ошибка: несовпадающие типы: ожидается i64, найдено &i64 (ожидается i64, найдено & -ptr) [E0308]

Task2_minimalcode.rs:7 if (k% p! = 0) {array.push (p)}; ^ ошибка: прерывание из-за двух предыдущих ошибок. Неудачная компиляция.


person Vega    schedule 07.02.2015    source источник


Ответы (2)


Произнесите сообщение об ошибке:

error: mismatched types: expected i64, found &i64 (expected i64, found &-ptr)

Vec<T>::iter дает вам итератор над &T (ссылки на T). Если вы не собираетесь когда-либо снова использовать vec, вы можете использовать for p in array или for p in array.into_iter(). Если вы действительно захотите использовать его снова, у вас есть несколько вариантов:

  • &array или array.iter() и разыменование p при его использовании.
  • array.iter().cloned()
  • array.iter().map(|e| *e) (фактически то же, что и выше)

Если все эти разговоры о ссылках не имеют смысла, вам, вероятно, следует прочитать раздел Rust Книга по указателям.

Помните, что вы можете обманом заставить компилятор сообщить вам тип переменной следующим образом: let _:() = p; - сообщение об ошибке будет содержать истинный тип.

person DK.    schedule 07.02.2015
comment
Мне снова нужен этот вектор. разыменование p при его использовании. Как я могу это сделать? & p не работает - person Vega; 07.02.2015
comment
&p принимает ссылку на p, *p разыменовывает ссылку p. Вам, вероятно, следует прочитать Книгу Ржавчины; вы не уйдете слишком далеко, не разобравшись со ссылками в Rust: они повсюду. - person DK.; 07.02.2015
comment
Я знаю, что такое ссылка / разграничение, но, исходя из управляемого кода (Java), мне трудно решить, когда и где его использовать :(. - person Vega; 07.02.2015
comment
Вот почему я рекомендовал книгу; дело не в абстрактном знании того, что они собой представляют, вам нужно понять, как они используются. - person DK.; 07.02.2015

Когда вы перебираете срез (который является видом на Vec), вы получаете ссылки на элементы в векторе, а не на сами элементы.

Вы можете исправить это двумя эквивалентными способами.

// Mark the iteration variable as a reference
for &p in &array {
    if (k % p != 0) {
        array.push(p)
    };
}

// Dereference the iteration variable
for p in &array {
    if (k % *p != 0) {
        array.push(*p)
    };
}

Однако затем вы сталкиваетесь со следующей проблемой: вы не можете изменить Vec, пока вы повторяете его! Если бы вам было разрешено, вектору, возможно, пришлось бы перераспределить память, которая его поддерживает, что, в свою очередь, сделало бы недействительными все ссылки в итераторе. Это сильный аргумент в пользу Rust - он не дает вам вот так прострелить себе ногу!

Не зная, что вы действительно хотите сделать, вот один из способов сделать это:

fn main() {
    let input_array = vec![2u64];
    let mut output_array = input_array.clone();

    for k in 3..13195 {
        for &p in &input_array {
            if k % p != 0 {
                output_array.push(p)
            };
        }
    }
}

Смотрите также:

person Shepmaster    schedule 07.02.2015
comment
Моя цель - задача 3 проекта Эйлера (projecteuler.net/problem=3), но, похоже, мне нужно чтобы получить лучший алгоритм. Буду надумать свою программу, спасибо за помощь :). - person Vega; 07.02.2015
comment
Насколько я понимаю, срез выдаст значения типа i32, правильно? Мне нужен фрагмент из usize значений, как это указать? - person Artyom Gevorgyan; 01.08.2020
comment
@ArtemHevorhian срез возвращает значения любого типа. В данном случае это Vec<u64>, поэтому для фрагментов и индексированных значений также будет использоваться u64. Измените тип фрагмента, чтобы изменить фрагменты и индексированные значения. - person Shepmaster; 03.08.2020