Arrays in Ruby
Arrays are ordered, integer-indexed collections of any object. They are one of Ruby's most fundamental data structures and provide powerful methods for data manipulation.
Creating Arrays
Basic Array Creation
# Empty array
empty = []
empty = Array.new
# Array with initial values
numbers = [1, 2, 3, 4, 5]
mixed = ["hello", 42, true, 3.14, :symbol, nil]
nested = [[1, 2], [3, 4], [5, 6]]
# Array with size and default value
zeros = Array.new(5, 0) # [0, 0, 0, 0, 0]
# Array with block initialization
squares = Array.new(5) { |i| i * i } # [0, 1, 4, 9, 16]
# Using %w and %i shortcuts
words = %w[apple banana cherry] # ["apple", "banana", "cherry"]
symbols = %i[red green blue] # [:red, :green, :blue]
Accessing Array Elements
arr = ["a", "b", "c", "d", "e"]
# Positive indexing (0-based)
puts arr[0] # "a" (first element)
puts arr[2] # "c" (third element)
# Negative indexing
puts arr[-1] # "e" (last element)
puts arr[-2] # "d" (second to last)
# Range access
puts arr[1..3] # ["b", "c", "d"]
puts arr[1...3] # ["b", "c"] (exclusive)
puts arr[1, 3] # ["b", "c", "d"] (start at 1, take 3)
# Methods for accessing
puts arr.first # "a"
puts arr.last # "e"
puts arr.first(2) # ["a", "b"]
puts arr.last(3) # ["c", "d", "e"]
puts arr.fetch(10, "default") # "default" (safe access)
puts arr.sample # Random element
Modifying Arrays
Adding Elements
arr = [1, 2, 3]
# Push (add to end)
arr.push(4) # [1, 2, 3, 4]
arr << 5 # [1, 2, 3, 4, 5]
arr.append(6) # [1, 2, 3, 4, 5, 6]
# Unshift (add to beginning)
arr.unshift(0) # [0, 1, 2, 3, 4, 5, 6]
# Insert at specific position
arr.insert(3, 2.5) # [0, 1, 2, 2.5, 3, 4, 5, 6]
# Concatenation
arr1 = [1, 2]
arr2 = [3, 4]
arr3 = arr1 + arr2 # [1, 2, 3, 4]
arr1.concat(arr2) # Modifies arr1: [1, 2, 3, 4]
Removing Elements
arr = [1, 2, 3, 4, 5, 3]
# Pop (remove from end)
last = arr.pop # Returns 3, arr = [1, 2, 3, 4, 5]
# Shift (remove from beginning)
first = arr.shift # Returns 1, arr = [2, 3, 4, 5]
# Delete specific value (all occurrences)
arr.delete(3) # Removes all 3s
# Delete at index
arr.delete_at(1) # Removes element at index 1
# Compact (remove nil values)
[1, nil, 2, nil, 3].compact # [1, 2, 3]
# Clear all elements
arr.clear # []
Array Iteration
Basic Iteration
fruits = ["apple", "banana", "cherry"]
# Each
fruits.each do |fruit|
puts fruit.upcase
end
# Each with index
fruits.each_with_index do |fruit, index|
puts "#{index}: #{fruit}"
end
# Reverse each
fruits.reverse_each { |fruit| puts fruit }
# Each slice
[1, 2, 3, 4, 5, 6].each_slice(2) do |pair|
puts pair.inspect # [1, 2], [3, 4], [5, 6]
end
Transformation Methods
numbers = [1, 2, 3, 4, 5]
# Map (creates new array)
squares = numbers.map { |n| n ** 2 } # [1, 4, 9, 16, 25]
# Map! (modifies original)
numbers.map! { |n| n * 2 } # numbers = [2, 4, 6, 8, 10]
# Select (filter)
evens = numbers.select { |n| n.even? } # [2, 4, 6, 8, 10]
odds = numbers.reject { |n| n.even? } # []
# Reduce/Inject
sum = [1, 2, 3, 4].reduce(:+) # 10
product = [1, 2, 3, 4].reduce(:*) # 24
sum = [1, 2, 3, 4].reduce(10) { |acc, n| acc + n } # 20 (with initial value)
# Partition
nums = [1, 2, 3, 4, 5, 6]
evens, odds = nums.partition(&:even?) # [[2, 4, 6], [1, 3, 5]]
Array Operations
Searching and Testing
arr = [1, 2, 3, 4, 5]
# Include?
puts arr.include?(3) # true
# Any? / All? / None?
puts arr.any? { |n| n > 3 } # true
puts arr.all? { |n| n > 0 } # true
puts arr.none? { |n| n < 0 } # true
# Find / Detect
first_even = arr.find { |n| n.even? } # 2
all_evens = arr.find_all { |n| n.even? } # [2, 4]
# Count
puts arr.count # 5
puts arr.count(3) # 1 (count occurrences)
puts arr.count { |n| n.even? } # 2
# Index / Rindex
puts arr.index(3) # 2
puts arr.rindex(3) # 2 (search from end)
Sorting and Ordering
# Sort
numbers = [3, 1, 4, 1, 5, 9]
sorted = numbers.sort # [1, 1, 3, 4, 5, 9]
numbers.sort! # Modifies original
# Sort with block
words = ["apple", "pie", "zoo", "banana"]
by_length = words.sort { |a, b| a.length <=> b.length }
by_reverse = words.sort { |a, b| b <=> a } # Descending
# Sort_by
people = [{name: "Alice", age: 30}, {name: "Bob", age: 25}]
by_age = people.sort_by { |person| person[:age] }
# Reverse
arr = [1, 2, 3]
reversed = arr.reverse # [3, 2, 1]
arr.reverse! # Modifies original
# Shuffle
shuffled = arr.shuffle # Random order
Set Operations
a = [1, 2, 3, 4]
b = [3, 4, 5, 6]
# Union
puts a | b # [1, 2, 3, 4, 5, 6]
# Intersection
puts a & b # [3, 4]
# Difference
puts a - b # [1, 2]
# Unique elements
arr = [1, 1, 2, 2, 3, 3]
puts arr.uniq # [1, 2, 3]
arr.uniq! # Modifies original
Advanced Array Methods
Flatten and Compact
# Flatten nested arrays
nested = [1, [2, 3], [4, [5, 6]]]
puts nested.flatten # [1, 2, 3, 4, 5, 6]
puts nested.flatten(1) # [1, 2, 3, 4, [5, 6]] (one level)
# Compact removes nil
arr = [1, nil, 2, nil, 3]
puts arr.compact # [1, 2, 3]
Zip and Transpose
# Zip combines arrays
names = ["Alice", "Bob", "Charlie"]
ages = [30, 25, 35]
combined = names.zip(ages) # [["Alice", 30], ["Bob", 25], ["Charlie", 35]]
# Transpose (for 2D arrays)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = matrix.transpose # [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Group and Chunk
# Group_by
words = ["apple", "banana", "cherry", "date", "elderberry"]
by_length = words.group_by(&:length)
# {5=>["apple"], 6=>["banana", "cherry"], 4=>["date"], 10=>["elderberry"]}
# Chunk
numbers = [1, 1, 2, 2, 2, 3, 1, 1]
chunks = numbers.chunk(&:itself).map { |n, arr| [n, arr.size] }
# [[1, 2], [2, 3], [3, 1], [1, 2]]
Practical Examples
Working with CSV-like Data
# Parse CSV-like data
data = "name,age,city\nAlice,30,NYC\nBob,25,LA"
lines = data.split("\n")
headers = lines.first.split(",")
records = lines[1..-1].map do |line|
values = line.split(",")
headers.zip(values).to_h
end
# [{name: "Alice", age: "30", city: "NYC"}, {name: "Bob", age: "25", city: "LA"}]
Array as Stack and Queue
# Stack (LIFO)
stack = []
stack.push(1) # [1]
stack.push(2) # [1, 2]
stack.pop # Returns 2, stack = [1]
# Queue (FIFO)
queue = []
queue.push(1) # [1]
queue.push(2) # [1, 2]
queue.shift # Returns 1, queue = [2]
Finding Duplicates
arr = [1, 2, 3, 2, 4, 3, 5]
duplicates = arr.select { |e| arr.count(e) > 1 }.uniq
# [2, 3]
# More efficient way
duplicates = arr.group_by(&:itself).select { |k, v| v.size > 1 }.keys
# [2, 3]
Performance Tips
- Use
<<instead ofpushfor single elements (slightly faster) - Pre-allocate arrays when size is known:
Array.new(1000) - Use
flat_mapinstead ofmap.flatten - For large arrays, consider using
Setfor lookups - Use bang methods (!) when you don't need the original array
Common Pitfalls
# Modifying during iteration (dangerous!)
arr = [1, 2, 3, 4, 5]
# DON'T DO THIS:
# arr.each { |n| arr.delete(n) if n.even? }
# DO THIS instead:
arr.delete_if { |n| n.even? }
# or
arr = arr.reject { |n| n.even? }
# Array references
a = [1, 2, 3]
b = a # b references same array
b << 4 # Both a and b are now [1, 2, 3, 4]
# To copy:
b = a.dup # Shallow copy
b = a.clone # Shallow copy with frozen state