πŸ“¦

Collections β€” When Array and Hash Become Vec and HashMap

Arrays and hashmaps in a type-fixed world

Vec β€” Ruby's Array

# Ruby β€” mix any types
arr = [1, "hello", true, nil]

// Rust β€” one type only
let arr: Vec<i32> = vec![1, 2, 3];
// vec![1, "hello"]  // compile error

Basic operations:

let mut v = vec![1, 2, 3];
v.push(4);              // Ruby: arr.push(4) / arr << 4
v.pop();                // Ruby: arr.pop
v.len();                // Ruby: arr.length
v[0];                   // Ruby: arr[0]
v.contains(&3);         // Ruby: arr.include?(3)
v.is_empty();           // Ruby: arr.empty?

HashMap β€” Ruby's Hash

# Ruby
h = { name: "sehwa", age: 30 }
h[:name]  # "sehwa"

// Rust
use std::collections::HashMap;

let mut h = HashMap::new();
h.insert("name", "sehwa");
h.insert("age", "30");  // values must be same type

h.get("name");  // Option<&&str> β€” None if missing (not nil!)

Ruby h[:missing] returns nil. Rust h.get("missing") returns None. Option handling required.

entry API β€” maps to Ruby's Hash.new(default)

# Ruby
counts = Hash.new(0)
words.each { |w| counts[w] += 1 }

// Rust
let mut counts = HashMap::new();
for word in &words {
    *counts.entry(word).or_insert(0) += 1;
}

entry().or_insert(0): "if key missing, insert 0; either way, return mutable reference to the value."

HashSet β€” Ruby's Set

use std::collections::HashSet;
let s: HashSet<i32> = [1, 2, 3].iter().cloned().collect();
s.contains(&2);  // true

Sorting

let mut v = vec![3, 1, 2];
v.sort();                          // [1, 2, 3] β€” mutates in place
users.sort_by(|a, b| a.age.cmp(&b.age));

Rust's sort() mutates the original (mut required). To preserve original, .clone() first.

Single-type constraint

Ruby's [1, "hello", true] won't work. For mixed types, use enum.

enum Value {
    Int(i32),
    Str(String),
    Bool(bool),
}
let mixed: Vec<Value> = vec![
    Value::Int(1),
    Value::Str("hello".into()),
    Value::Bool(true),
];

Verbose, but type checking when extracting means fewer runtime errors.

Key Points

1

Array β†’ Vec<T>, Hash β†’ HashMap<K, V> β€” type parameter required

2

Hash.get() returns Option β€” None instead of nil

3

entry().or_insert() for default value pattern

4

Wrap in enum to hold multiple types

Pros

  • Fixed types mean no type casting when extracting
  • get() returning Option means no index errors

Cons

  • Type constraints feel restrictive compared to Ruby's flexible arrays
  • HashMap initialization is more verbose than Ruby Hash literals

Use Cases

Data grouping/counting β€” HashMap + entry pattern API response parsing β€” type-safe with Vec<Item>