Создание вектора с непостоянной длиной
Я хочу создать вектор, но я знаю только размер, который я хочу, чтобы вектор находился во время выполнения. Вот как я делаю это сейчас (т.е. Создавая пустой, изменяемый вектор и добавляя к нему векторы):
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.
Ответы
Ответ 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