153

I'd like to initialize a vector of zeros with a specific size that is determined at runtime.

In C, it would be like:

int main(void)
{
    uint size = get_uchar();
    int A[size][size];
    memset(A, 0, size*size*sizeof(int));
}

Here's the helper function that I tried writing in Rust, but I think the slicing syntax 0..size is offending the compiler. Besides, it looks more verbose than the C version. Is there a more idiomatic way to do this?

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;
}

I swear that the old docs used to explain a from_elem() method here and none of the permutations of the [0 ; size] notation seem to work

I'd like to stick this into a substring search algorithm ultimately:

pub fn kmp(text: &str, pattern: &str) -> i64 {
    let mut shifts = zeros(pattern.len()+1);
}
elleciel
  • 2,297
  • 3
  • 17
  • 19

4 Answers4

200

To initialize a vector of zeros (or any other constant value) of a given length, you can use the vec! macro:

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

That said, your function worked for me after just a couple syntax fixes:

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 no longer exists in Rust 1.0, size needed to be cast as usize, and the types for the vectors needed to match (changed let mut zero_vec: Vec<i64> to let mut zero_vec: Vec<i32>.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
anderspitman
  • 9,230
  • 10
  • 40
  • 61
  • 6
    I updated Rust to 1.0 and `let mut shifts = vec![0; pattern.len()];` works directly now... Oops. Before this I had an `error: expected `:`, found `.` ../search.rs:17 zero_vec.push(0);` which made no sense. – elleciel Apr 09 '15 at 06:12
  • 3
    I've been there myself. When I was very first starting out it was very hard to know whether I was using syntax incorrectly, or the syntax had just changed since the last time I updated or since the doc I was reading was updated. I'm really glad we have the beta now and way excited for 1.0. Btw are you using `rustup.sh` to update Rust? If so you might want to get the latest version of the script, which will grab the beta now instead of nightlies. – anderspitman Apr 09 '15 at 06:16
  • 3
    But that's why I like most about the language - the community support is wonderful, no downvotes for my noob question. :) Yep I curl'ed the latest `rustup.sh`. Thanks so much! Now I just have to figure out index access to string elements... – elleciel Apr 09 '15 at 06:18
  • Of course, you may ask yourself why you would have to lookup answers for so basic a question in the first place. This is more intuitive in most other languages, e.g. those that default to zero when an array / vector is initialized. – Maarten Bodewes Jan 17 '19 at 12:52
  • A very noob question but when I did this I ended up with a 2 element vector of 0 and 3 in which the size I was trying to initialize it to was 3. Is there some criteria that would cause the initialization to behavior differently? – Tedford Jun 27 '20 at 19:12
18

Here is another way, much shorter. It works with 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)
    }
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
VRage
  • 1,458
  • 1
  • 15
  • 27
15

You can also use the iter::repeat function, which I suppose is "more idiomatic" (and just looks nicer to me):

use std::iter;

fn zeros(size: usize) -> Vec<i32> {
    iter::repeat(0).take(size).collect()
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
tckmn
  • 57,719
  • 27
  • 114
  • 156
  • Is that considered more idiomatic than using vec! directly? Would that run faster? – anderspitman Apr 09 '15 at 15:49
  • @anders No idea; I agree that the `vec!` version looks nice as well. I suppose it couldn't hurt to try some benchmarks, which I might do when I get home. – tckmn Apr 09 '15 at 16:52
  • Yeah you've got me wondering now what the implementation of vec! is. I'll see if I can find some time to dig into this a little. – anderspitman Apr 09 '15 at 16:54
  • 14
    Using the vec macro is considered more idiomatic, it was added specifically because people did not want to do this. – Steve Klabnik Apr 10 '15 at 13:48
  • 1
    Note: `::>` is superfluous, type inference can figure it out automatically since it *has* to be the type of the expression, so you can just use `.collect()` here. – Matthieu M. Apr 10 '15 at 18:13
7

You may use resize

let mut v = Vec::new();
let l = 42;
v.resize(l, 0u32);
lu_zero
  • 978
  • 10
  • 14
  • 14
    `vec!` is more efficient when allocating with 0 because it uses `RawVec::with_capacity_zeroed()`, while `.resize()` calls `.extend_with()` which uses a more complex value generator. For other values both use `.extend_with()` so the benefit is roughly the same. – Jocelyn Mar 29 '18 at 11:55