liveBook · Manning

Vector

As explained in Rust in Action: Systems programming concepts and techniques

A vector is a dynamically resizable, ordered collection of elements.

A Rust vector, written `Vec<T>`, is a growable list of values of type `T`. Unlike a fixed-width array, it can change size while a program runs. That flexibility requires extra bookkeeping and carries a small runtime cost, but `Vec<T>` is often the first list-like type to reach for. section 2.10 section 2.10.3 section 2.15

Collecting CSV fields

To process a CSV record, split it at commas, trim each field, and collect the results into `let fields: Vec<_> = record.split(',').map(|field| field.trim()).collect();`. The underscore lets Rust infer the element type. The resulting fields can be read by position, as in `fields[0]` and `fields[1]`. section 1.5

Vectors also help when the number of search results is not known in advance. In a grep-like search, `vec![]` starts an empty vector and `push` adds a matching line’s index. A `Vec<Vec<(usize, String)>>` can hold separate groups of nearby lines; each inner vector stores line numbers paired with text. `Vec::with_capacity(...)` supplies a size estimate for an inner vector and can reduce repeated memory allocation. section 2.10.3

Listing 2.22 Enabling context lines to be printed out with a Vec<Vec<T>>
 fn main() {
   let ctx_lines = 2;
   let needle = "oo";
   let haystack = "\
 Every face, every shop,
 bedroom window, public-house, and
 dark square is a picture
 feverishly turned--in search of what?
 It is the same with books.
 What do we seek
 through millions of pages?";
 
   let mut tags: Vec<usize> = vec![];                     #1
   let mut ctx: Vec<Vec<(
                usize, String)>> = vec![];                #2
 
   for (i, line) in haystack.lines().enumerate() {        #3
     if line.contains(needle) {
       tags.push(i);
 
       let v = Vec::with_capacity(2*ctx_lines + 1);       #4
       ctx.push(v);
     }
   }
 
   if tags.is_empty() {                                   #5
     return;
   }
 
   for (i, line) in haystack.lines().enumerate() {        #6
     for (j, tag) in tags.iter().enumerate() {
       let lower_bound =
           tag.saturating_sub(ctx_lines);                 #7
       let upper_bound =
           tag + ctx_lines;
 
       if (i >= lower_bound) && (i <= upper_bound) {
           let line_as_string = String::from(line);       #8
           let local_ctx = (i, line_as_string);
           ctx[j].push(local_ctx);
       }
     }
   }
 
   for local_ctx in ctx.iter() {
     for &(i, ref line) in local_ctx.iter() {             #9
      let line_num = i + 1;
       println!("{}: {}", line_num, line);
     }
   }
 }

Follow the first pass of the search: it tags matching lines and creates an inner vector for each match before collecting context lines in a second pass. section 2.10.3

For raw bytes, `Vec<u8>` is a growable counterpart to a `[u8]` slice. This distinction matters when text may contain invalid UTF-8: reading it directly as `String` can fail, so byte data may need to be decoded with knowledge of its source. section 2.9 section 2.10.3

How Rust in Action: Systems programming concepts and techniques covers it

How deep it goes
Defines `Vec<T>` and works through creation, nesting, and capacity hints; stops short of implementing a vector.
Examples
Uses collected CSV fields and a two-pass grep-like search that groups numbered context lines.
What it assumes
Introduces arrays and slices before vectors, then uses basic Rust loops and string methods in the search example.
What you can do after
Operates Rust's `Vec<T>` with `vec![]`, `push`, and `Vec::with_capacity` to collect search context.
How it connects
Connects vectors to arrays, slices, tuples, iterators, strings, and UTF-8 decoding.

Also explained in

Compare how 11 books explain vector →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Rust in Action: Systems programming concepts and techniques. The section links point to the parts of the book it draws on.