Подтвердить что ты не робот

Создание вектора с непостоянной длиной

Я хочу создать вектор, но я знаю только размер, который я хочу, чтобы вектор находился во время выполнения. Вот как я делаю это сейчас (т.е. Создавая пустой, изменяемый вектор и добавляя к нему векторы):

fn add_pairs(pairs: ~[int]) -> ~[int] {
    let mut result : ~[int] = ~[];
    let mut i = 0;
    while i < pairs.len() {
        result += ~[pairs[i] + pairs[i + 1]];
        i += 2;
    }
    return result;
}

Вот как я хочу это сделать (т.е. создать вектор и поместить в него все, вместо того, чтобы добавлять много векторов вместе):

fn add_pairs(pairs: ~[int]) -> ~[int] {
    let number_of_pairs = pairs.len() / 2;
    let result : ~[int, ..number_of_pairs];
    let mut i = 0;
    while i < pairs.len() {
        result[i] = pairs[2 * i] + pairs[2 * i + 1];
        i += 1;
    }
    return result;
}

К сожалению, выполнение приведенного выше дает мне что-то вроде:

error: expected constant expr for vector length: Non-constant path in constant expr
let result: ~[int, ..number_of_pairs];
             ^~~~~~~~~~~~~~~~~~~~~~~~

У меня создается впечатление, что векторы должны иметь свой размер во время компиляции (и поэтому вам нужно установить их размер в константу). Исходя из фона Java, я смущен! Есть ли способ создать вектор, размер которого вы знаете только во время выполнения?

Я использую Rust 0.6.

4b9b3361

Ответ 1

Невозможно создать вектор постоянной длины с длиной, определенной во время выполнения, допускаются только векторы постоянной длины компиляции, поэтому (варианты) ваш первый метод с ~[int] является единственным поддерживаемым способом. Вы можете использовать vec::from_elem(number_of_pairs, 0), чтобы создать вектор нужного размера и использовать вторую часть.


Есть много вспомогательных функций для того, что вы пытаетесь сделать (используя while прямо Rust должен быть очень редок):

fn add_pairs(pairs: &[int]) -> ~[int] {
    let mut result = ~[];
    for i in uint::range(0, pairs.len() / 2) {
        result.push(pairs[2*i] + pairs[2*i+1])
    }
    result
}

Или даже

fn add_pairs(pairs: &[int]) -> ~[int] {
    pairs.chunks(2).filter(|x| x.len() == 2).map(|x| x[0] + x[1]).collect()
}

Документы: chunks, filter, map, collect. (filter только потому, что последний элемент chunks может иметь длину 1.)

(Также обратите внимание, что добавление двух векторов выделяет целое новое, а push не делает этого обязательно и намного быстрее (и .collect похоже).

Ответ 2

В версии Rust 1.0.0 они создали стабильную структуру std::vec:Vec, чтобы вы могли создать экземпляр растущего вектора с помощью let mut my_vec = Vec::new();. Вы также можете использовать макрос vec! следующим образом: let mut another_vec = vec![1isize, 2isize, 3isize]; Что важно что в обоих случаях переменная, которую вы назначаете, должна быть изменчивой.

С помощью этих векторов вы можете вызвать my_vec.push(num); для отдельных элементов (стабильный) или another_vec.push_all(["list", "of", "objects"]); (неустойчивый), чтобы добавить элементы в конец вектора.

Итак, для вашей конкретной проблемы вы можете сделать что-то вроде этого

fn add_pairs(pairs: Vec<(Vec<isize>)>) -> Vec<isize> {
    let mut result = Vec::new();
    for pair in pairs.iter() {
        result.push(pair[0]);
        result.push(pair[1]);
    }
    return result
}

Вы можете видеть это в действии здесь, где у вас (я предположил) был вложенным вектором целочисленных пар.

Ответ 3

В более поздних версиях Rust (я использую 0.9) теперь в std::vec есть функция with_capacity(), которая обрабатывает этот сценарий.

Пример кода:

use std::vec;

// ...

let n = 44;  // pretend determined at run time
let mut v = vec::with_capacity::<f64>(n);
v.push(6.26);
println("{:?}", v);             // prints ~[6.26f64]
println("{:?}", v.len());       // prints 1u
println("{:?}", v.capacity());  // prints 44u