Skip to content

Vector

What is a Vector?

A Vector is an ordered, 0-indexed list of values. Vectors can hold any mix of types — integers, strings, booleans, other vectors, hashes. They are Frankie's most-used composite type and the foundation of the R-inspired statistical functions.

numbers = [1, 2, 3, 4, 5]
mixed   = [42, "hello", true, nil, 3.14]
empty   = []
nested  = [[1, 2], [3, 4], [5, 6]]

Vectors are mutable — their contents can be changed after creation.


Creating Vectors

# Literal
v = [10, 20, 30]

# From a range
v = vec(1..10)      # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
v = vec(0...5)      # [0, 1, 2, 3, 4]

# From seq()
v = seq(0, 10, 2)   # [0, 2, 4, 6, 8, 10]
v = seq(1.0, 2.0, 0.25)  # [1.0, 1.25, 1.5, 1.75, 2.0]

# Repetition
v = [0] * 5         # [0, 0, 0, 0, 0]
v = [1, 2] * 3      # [1, 2, 1, 2, 1, 2]

Accessing Elements

Vectors are 0-indexed. Negative indices count from the end.

v = [10, 20, 30, 40, 50]

puts v[0]     # 10  — first
puts v[2]     # 30
puts v[-1]    # 50  — last
puts v[-2]    # 40

# Out of range returns nil
puts v[99]    # nil

Slicing

v = [10, 20, 30, 40, 50]

puts v[1..3]    # [20, 30, 40]  — inclusive
puts v[1...3]   # [20, 30]      — exclusive
puts v[-3..-1]  # [30, 40, 50]  — last three
puts v[0..1]    # [10, 20]      — first two

Assignment

v = [1, 2, 3, 4, 5]
v[0] = 99
puts v   # [99, 2, 3, 4, 5]

v[-1] = 0
puts v   # [99, 2, 3, 4, 0]

Basic Operations

v = [1, 2, 3, 4, 5]

puts v.length    # 5
puts v.first     # 1
puts v.last      # 5
puts v.empty?    # false
puts [].empty?   # true

puts v.include?(3)   # true
puts v.include?(9)   # false

Adding and Removing Elements

v = [1, 2, 3]

v.push(4)        # append — v is now [1, 2, 3, 4]
v.pop()          # remove last — returns 4, v is now [1, 2, 3]

v.delete(2)      # remove by value — v is now [1, 3]
puts v           # [1, 3]

R-style Vectorised Arithmetic

Operations on vectors apply element-wise — borrowed from R:

v = [1, 2, 3, 4, 5]

puts v * 2              # [2, 4, 6, 8, 10]
puts v + [10, 10, 10, 10, 10]   # [11, 12, 13, 14, 15]
puts v ** 2             # [1, 4, 9, 16, 25]

Vectors of different lengths raise a runtime error for arithmetic. For pairing, use .zip instead.


Statistical Functions

data = [23, 45, 12, 67, 34, 89, 56]

puts sum(data)      # 326
puts mean(data)     # 46.57...
puts median(data)   # 45
puts min(data)      # 12
puts max(data)      # 89
puts stdev(data)    # 24.9...
puts variance(data) # 621.6...

Also as methods:

puts data.sum    # 326
puts data.min    # 12
puts data.max    # 89
puts data.mean   # 46.57...

Sorting and Ordering

v = [3, 1, 4, 1, 5, 9, 2, 6]

puts v.sort             # [1, 1, 2, 3, 4, 5, 6, 9]
puts v.reverse          # [6, 2, 9, 5, 1, 4, 1, 3]
puts v.uniq             # [3, 1, 4, 5, 9, 2, 6]  — deduped

# Sort by computed key
words = ["banana", "fig", "apple", "cherry"]
puts words.sort_by do |w| w.length end   # [fig, apple, banana, cherry]
puts words.sort_by do |w| w end          # [apple, banana, cherry, fig]

# Min/max by key
puts words.min_by do |w| w.length end    # fig
puts words.max_by do |w| w.length end    # banana

Transformation

v = [1, 2, 3, 4, 5]

# map — transform each element
puts v.map do |x| x * x end          # [1, 4, 9, 16, 25]
puts v.map do |x| x.to_s end         # ["1", "2", "3", "4", "5"]

# select / reject — filter
puts v.select do |x| x > 3 end       # [4, 5]
puts v.reject do |x| x > 3 end       # [1, 2, 3]

# reduce — fold into a single value
puts v.reduce(0) do |acc, x| acc + x end   # 15
puts v.reduce(1) do |acc, x| acc * x end   # 120

# flat_map — map then flatten one level
puts [[1,2],[3,4]].flat_map do |sub| sub end       # [1, 2, 3, 4]
puts ["hi","bye"].flat_map do |w| w.chars end       # [h,i,b,y,e]

# map_with_index — element and position together
puts v.map_with_index do |x, i| "#{i}:#{x}" end
# ["0:1", "1:2", "2:3", "3:4", "4:5"]

Searching

v = [1, 2, 3, 4, 5, 6]

# find — first matching element
puts v.find do |x| x > 4 end       # 5

# any? / all? / none?
puts v.any?  do |x| x > 5 end      # true
puts v.all?  do |x| x > 0 end      # true
puts v.none? do |x| x > 9 end      # true

# count — with a block
puts v.count do |x| x.even? end    # error — .even? not available
puts v.count do |x| x % 2 == 0 end # 3

Grouping and Bucketing

v = [1, 2, 3, 4, 5, 6]

# tally — count occurrences
puts ["a","b","a","c","b","a"].tally   # {a: 3, b: 2, c: 1}

# group_by — bucket by key
by_parity = v.group_by do |x|
  if x % 2 == 0 then "even" else "odd" end
end
puts by_parity["even"]   # [2, 4, 6]
puts by_parity["odd"]    # [1, 3, 5]

# chunk — fixed-size sub-vectors
puts v.chunk(2)   # [[1,2],[3,4],[5,6]]

Iteration with State

# each_with_object — shared accumulator
freq = ["a","b","a","c","b","a"].each_with_object({}) do |x, h|
  cur = h[x]
  h[x] = (if cur == nil then 0 else cur end) + 1
end
puts freq   # {a: 3, b: 2, c: 1}

# each_with_index
["x", "y", "z"].each_with_index do |val, i|
  puts "#{i}: #{val}"
end

# each_slice — non-overlapping windows
[1,2,3,4,5,6].each_slice(2) do |s|
  puts s
end
# [1, 2]  [3, 4]  [5, 6]

# each_cons — sliding window
[1,2,3,4,5].each_cons(3) do |w|
  puts w
end
# [1,2,3]  [2,3,4]  [3,4,5]

Combining Vectors

a = [1, 2, 3]
b = [4, 5, 6]

# zip — pair elements
puts a.zip(b)      # [[1,4],[2,5],[3,6]]

# zip_with — pair and transform
puts a.zip_with(b) do |x, y| x + y end   # [5, 7, 9]

# product — cartesian product
puts [1,2].product([3,4])   # [[1,3],[1,4],[2,3],[2,4]]

# flatten — deep flatten
puts [[1,[2]],[3,[4,5]]].flatten     # [1, 2, 3, 4, 5]
puts [[1,[2]],[3,[4,5]]].flatten(1)  # [1, [2], 3, [4, 5]]

# compact — remove nils
puts [1, nil, 2, nil, 3].compact   # [1, 2, 3]

# unzip — split pairs back into two vectors
puts unzip([[1,"a"],[2,"b"],[3,"c"]])   # [[1,2,3],["a","b","c"]]

The Pipe Operator

Vectors work naturally with |>:

data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]

data |> sum  |> puts    # 39
data |> mean |> puts    # 3.9
data |> min  |> puts    # 1
data |> max  |> puts    # 9

Quick Reference

Category Method / Function
Access [i] [a..b] .first .last .take(n) .drop(n) .dig(...)
Inspect .length .empty? .include?(x) .count .tally
Mutate .push(x) .pop() .delete(x) [i]=
Transform .map .flat_map .map_with_index .reverse .flatten .compact
Filter .select .reject .find .uniq
Aggregate .reduce .each_with_object .sum .min .max .mean
Test .any? .all? .none? .count do
Sort .sort .sort_by .min_by .max_by .reverse
Group .group_by .chunk .each_slice .each_cons
Combine .zip .zip_with .product .flatten unzip()
Stats sum() mean() median() stdev() variance() min() max()
Create vec(range) seq(start, stop, step) [x] * n