490: Fixed-Size String Arrays
Difficulty: 1 Level: Beginner Store and work with collections of strings โ both fixed-size arrays and growable vectors.The Problem This Solves
When you have a known set of strings โ days of the week, command names, error messages โ you don't need a heap-allocated dynamic collection. A fixed-size array `[&str; 7]` lives on the stack, costs nothing to allocate, and conveys your intent: this list doesn't grow. But often you need to sort, filter, or search string collections. Whether you use `[&str; N]`, `Vec<&str>`, or `Vec<String>` depends on ownership: do you own the strings or just borrow them? This example shows the idiomatic patterns: when to use each type, how to sort case-insensitively, how to filter, and how to join a collection back into a single string.The Intuition
Three string collection types:- `[&str; N]` โ fixed-size, stack-allocated, borrowed โ great for static data
- `Vec<&str>` โ growable, borrowed โ when you slice from owned data
- `Vec<String>` โ growable, owned โ when you produce or mutate strings
How It Works in Rust
// Fixed array โ stack allocated, no heap
let days: [&str; 7] = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
// Slice operations work on both arrays and Vecs
println!("{}", days.contains(&"Wed")); // true
// Sort a Vec (arrays can't be sorted in-place while borrowed)
let mut words = vec!["banana", "apple", "cherry"];
words.sort(); // lexicographic
// Case-insensitive sort
words.sort_by_key(|s| s.to_lowercase());
// Filter: retain keeps elements matching a predicate
let mut items: Vec<&str> = vec!["rust", "ruby", "go", "python"];
items.retain(|s| s.starts_with('r'));
// items == ["rust", "ruby"]
// Join: collect a slice into a single string
let joined = words.join(", "); // "apple, banana, cherry"
// Search
let pos = words.iter().position(|&s| s == "banana");
What This Unlocks
- Build lookup tables and menus as zero-cost `[&str; N]` arrays
- Sort and filter lists of labels, tags, or command names idiomatically
- Join display strings with `join()` โ replacing manual string concatenation loops
Key Differences
| Concept | OCaml | Rust | |||
|---|---|---|---|---|---|
| Fixed string array | `let a = [ | "a"; "b" | ]` | `let a: [&str; 2] = ["a", "b"]` | |
| Sort | `Array.sort compare a` | `vec.sort()` (in-place) | |||
| Filter | `Array.to_list a \ | > List.filter f` | `vec.retain(\ | s\ | pred(s))` |
| Join | `String.concat sep list` | `slice.join(sep)` | |||
| Contains | `Array.mem x a` | `slice.contains(&x)` |
// 490. Fixed-size string arrays
fn main() {
// &str array โ compile-time known size
let fruits: [&str; 5] = ["banana","apple","cherry","date","elderberry"];
println!("count: {}", fruits.len());
println!("first: {}", fruits[0]);
println!("contains cherry: {}", fruits.contains(&"cherry"));
// Sort a Vec<String>
let mut words: Vec<String> = fruits.iter().map(|&s| s.to_string()).collect();
words.sort();
println!("sorted: {:?}", words);
// Case-insensitive sort
let mut mixed = vec!["Banana","apple","Cherry","DATE"];
mixed.sort_by_key(|s| s.to_lowercase());
println!("case-insensitive: {:?}", mixed);
// Filter
let long: Vec<&str> = fruits.iter().copied().filter(|s| s.len() > 5).collect();
println!("len>5: {:?}", long);
// Map + collect
let upper: Vec<String> = fruits.iter().map(|s| s.to_uppercase()).collect();
println!("upper[0]: {}", upper[0]);
// Join
println!("joined: {}", fruits.join(", "));
// Total chars
let total: usize = fruits.iter().map(|s| s.len()).sum();
println!("total chars: {}", total);
// Binary search (requires sorted)
words.sort();
match words.binary_search(&"cherry".to_string()) {
Ok(i) => println!("cherry at index {}", i),
Err(i) => println!("cherry not found, would insert at {}", i),
}
}
#[cfg(test)]
mod tests {
#[test] fn test_sort() { let mut v=vec!["c","a","b"]; v.sort(); assert_eq!(v,["a","b","c"]); }
#[test] fn test_filter() { let v=vec!["hi","hello","hey"]; let long:Vec<_>=v.iter().filter(|s|s.len()>2).collect(); assert_eq!(long.len(),1); }
#[test] fn test_join() { assert_eq!(["a","b","c"].join("-"),"a-b-c"); }
#[test] fn test_bsearch() { let v=vec!["apple".to_string(),"banana".to_string()]; assert_eq!(v.binary_search(&"banana".to_string()),Ok(1)); }
}
(* 490. String arrays โ OCaml *)
let () =
let words = [|"banana";"apple";"cherry";"date";"elderberry"|] in
Array.sort String.compare words;
Printf.printf "sorted: %s\n" (String.concat " " (Array.to_list words));
let long = Array.to_list words |> List.filter (fun s -> String.length s > 5) in
Printf.printf "long: %s\n" (String.concat " " long);
Printf.printf "has cherry: %b\n" (Array.exists ((=) "cherry") words);
Printf.printf "total chars: %d\n"
(Array.fold_left (fun a s -> a + String.length s) 0 words)