Створення вектора нулів для певного розміру


80

Я хотів би ініціалізувати вектор нулів із певним розміром, який визначається під час виконання.

У C це буде так:

Ось допоміжна функція, яку я намагався писати в Rust, але я думаю, що синтаксис нарізки 0..sizeображає компілятор. До того ж, це виглядає більш багатослівно, ніж версія C. Чи є більш ідіоматичний спосіб зробити це?

fn zeros(size: u32) -> Vec<i32> {
    let mut zero_vec: Vec<i32> = Vec::with_capacity(size);
    for i in 0..size {
        zero_vec.push(0);
    }
    return zero_vec;
}

Клянусь, що старі документи використовували тут пояснення from_elem()методу, і, здається, жодна з перестановок нотації не працює[0 ; size]

Я хотів би вкласти це в алгоритм пошуку підрядків:

pub fn kmp(text: &str, pattern: &str) -> i64 {
    let mut shifts = zeros(pattern.len()+1);
}

Відповіді:


98

Для ініціалізації вектора нулів (або будь-якого іншого постійного значення) заданої довжини можна використовувати vec!макрос:

let len = 10;
let zero_vec = vec![0; len];

Тим не менш, ваша функція спрацювала для мене після декількох виправлень синтаксису:

fn zeros(size: u32) -> Vec<i32> {
    let mut zero_vec: Vec<i32> = Vec::with_capacity(size as usize);
    for i in 0..size {
        zero_vec.push(0);
    }
    return zero_vec;
}

uintбільше не існує в Rust 1.0, його sizeпотрібно було відтворити як usize, і типи для векторів, які повинні збігатися (змінено let mut zero_vec: Vec<i64>на let mut zero_vec: Vec<i32>.


4
Я оновив Rust до 1.0 і let mut shifts = vec![0; pattern.len()];працює безпосередньо зараз ... На жаль. До цього у мене було error: expected : , found .` ../search.rs:17 zero_vec.push (0); `що не мало сенсу.
elleciel

3
Я був там сам. Коли я вперше починав працювати, було дуже важко зрозуміти, чи використовую я синтаксис неправильно, чи синтаксис щойно змінився з моменту останнього оновлення чи з часу оновлення документа, який я читав. Я дуже радий, що у нас є бета-версія зараз, і ми дуже раді для версії 1.0. До речі, ви використовуєте rustup.shдля оновлення Rust? Якщо це так, ви можете отримати останню версію сценарію, яка захопить бета-версію замість Nightlies.
anderspitman

2
Але саме тому мені найбільше подобається мова - підтримка спільноти чудова, немає голосів проти мого запитання про нуб. :) Так, я згорнувся останнім rustup.sh. Дуже дякую! Тепер мені просто потрібно з’ясувати доступ до індексу до рядкових елементів ...
elleciel

Звичайно, ви можете запитати себе, чому спочатку вам потрібно було б знайти відповіді на таке основне питання. Це є більш інтуїтивно зрозумілим у більшості інших мов, наприклад, тих, які за замовчуванням дорівнюють нулю при ініціалізації масиву / вектора.
Maarten Bodewes

Дуже нуб-питання, але коли я це зробив, у мене з’явився вектор 2 елементів 0 і 3, розмір якого я намагався його ініціалізувати дорівнював 3. Чи існують деякі критерії, які могли б спричинити поведінку ініціалізації інакше?
Тедфорд,

14

Ось інший спосіб, набагато коротший. Він працює з Rust 1.0:

fn zeros(size: u32) -> Vec<i32> {
    vec![0; size as usize]
}

fn main() {
    let vec = zeros(10);
    for i in vec.iter() {
        println!("{}", i)
    }
}

3
Чим це відрізняється від останньої частини відповіді @anders?
Шепмастер

10

Ви також можете скористатися iter::repeatфункцією, яка, на мою думку, є "більш ідіоматичною" (і мені це просто виглядає приємніше):

use std::iter;

fn zeros(size: usize) -> Vec<i32> {
    iter::repeat(0).take(size).collect()
}

Це вважається більш ідіоматичним, ніж використання vec! безпосередньо? Це швидше пробігло б?
anderspitman

@anders Немає ідеї; Я згоден, що vec!версія також виглядає добре. Я гадаю, це не могло зашкодити спробувати деякі тести, які я міг би зробити, повернувшись додому.
tckmn

Так, у вас мене зараз цікавить, що таке реалізація vec! є. Я подивлюсь, чи знайду я трохи часу, щоб трохи вкопатися в цьому.
anderspitman

8
Використання макрокоманди vec вважається більш ідіоматичним, її додали спеціально через те, що люди не хотіли цього робити.
Steve Klabnik

1
Примітка: ::<Vec<i32>>зайве, висновок типу може зрозуміти це автоматично, оскільки це має бути тип виразу, тому ви можете просто використовувати .collect()тут.
Matthieu M.

3

Ви можете використовувати розмір

let mut v = Vec::new();
let l = 42;
v.resize(l, 0u32);

6
vec!є більш ефективним при розподілі з 0, оскільки він використовує RawVec::with_capacity_zeroed(), тоді як .resize()виклики .extend_with()використовують більш складний генератор значень. Для інших значень обидва використовують, .extend_with()тому вигода приблизно однакова.
Джоселін,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.