How to Work with Arrays in Ruby
· 6 min read · Updated March 12, 2026 · beginner
ruby arrays guide
Arrays are one of the most frequently used data structures in Ruby. This cookbook provides practical recipes for common array operations.
Creating Arrays
From Scratch
Create an array with literal syntax:
numbers = [1, 2, 3, 4, 5]
words = ["apple", "banana", "cherry"]
mixed = [1, "two", 3.0, nil]
With Array.new
Use Array.new when you need a specific size or default values:
# Create array with 5 nil elements
empty = Array.new(5)
# => [nil, nil, nil, nil, nil]
# Create array with 5 elements set to 0
zeros = Array.new(5, 0)
# => [0, 0, 0, 0, 0]
# Create array with block (each element computed)
squares = Array.new(5) { |i| i ** 2 }
# => [0, 1, 4, 9, 16]
The block form is preferred when each element needs a unique value, because the single-value form can cause issues with mutable objects.
From Other Objects
Convert ranges, strings, and other objects to arrays:
# Range to array
(1..10).to_a
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# String to array of characters
"hello".chars
# => ["h", "e", "l", "l", "o"]
# String to array of words
"hello world".split
# => ["hello", "world"]
# CSV or delimited string
"a,b,c".split(",")
# => ["a", "b", "c"]
Adding and Removing Elements
Adding Elements
# Append to end
array = [1, 2, 3]
array << 4
array.push(5, 6)
# => [1, 2, 3, 4, 5, 6]
# Prepend to beginning
array.unshift(0)
# => [0, 1, 2, 3, 4, 5, 6]
# Insert at specific index
array.insert(2, "two")
# => [0, 1, "two", 2, 3, 4, 5, 6]
Removing Elements
array = [1, 2, 3, 4, 5]
# Remove and return last element
last = array.pop
# last = 5, array = [1, 2, 3, 4]
# Remove and return first element
first = array.shift
# first = 1, array = [2, 3, 4]
# Remove element at specific index
array.delete_at(1)
# array = [2, 4]
# Remove all elements that match
array = [1, 2, 3, 2, 4]
array.delete(2)
# array = [1, 3, 4]
Searching and Filtering
Finding Elements
fruits = ["apple", "banana", "cherry", "date"]
# Find first match
fruits.find { |f| f.length > 5 }
# => "banana"
# Find index of first match
fruits.index { |f| f.start_with?("c") }
# => 2
# Check if any element matches
fruits.any? { |f| f.start_with?("b") }
# => true
# Check if all elements match
fruits.all? { |f| f.length < 10 }
# => true
Filtering Arrays
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Select elements matching condition
evens = numbers.select { |n| n.even? }
# => [2, 4, 6, 8, 10]
# Reject elements matching condition
odds = numbers.reject { |n| n.even? }
# => [1, 3, 5, 7, 9]
# Partition into matching/non-matching
evens, odds = numbers.partition { |n| n.even? }
# evens = [2, 4, 6, 8, 10], odds = [1, 3, 5, 7, 9]
Transforming Arrays
Map and Friends
numbers = [1, 2, 3, 4, 5]
# Transform each element
squared = numbers.map { |n| n ** 2 }
# => [1, 4, 9, 16, 25]
# Transform and flatten (for nested results)
nested = numbers.flat_map { |n| [n, n * 2] }
# => [1, 2, 2, 4, 3, 6, 4, 8, 5, 10]
# Collect is alias for map
doubled = numbers.collect { |n| n * 2 }
# => [2, 4, 6, 8, 10]
Chaining Transformations
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Chain filter, transform, and limit
result = numbers
.select { |n| n > 3 }
.map { |n| n ** 2 }
.take(3)
# => [16, 25, 36]
Sorting Arrays
Basic Sorting
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
# Sort ascending
numbers.sort
# => [1, 1, 2, 3, 4, 5, 6, 9]
# Sort descending
numbers.sort.reverse
# => [9, 6, 5, 4, 3, 2, 1, 1]
# Sort with block
numbers.sort { |a, b| b <=> a }
# => [9, 6, 5, 4, 3, 2, 1, 1]
Custom Object Sorting
users = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 25 },
{ name: "Charlie", age: 35 }
]
# Sort by age
users.sort_by { |u| u[:age] }
# => [{:name=>"Bob", :age=>25}, {:name=>"Alice", :age=>30}, {:name=>"Charlie", :age=>35}]
# Sort by name length
users.sort_by { |u| u[:name].length }
# => [{:name=>"Bob", :age=>25}, {:name=>"Alice", :age=>30}, {:name=>"Charlie", :age=>35}]
Iterating Efficiently
Each Variations
fruits = ["apple", "banana", "cherry"]
# Each with index
fruits.each_with_index { |fruit, i| puts "#{i}: #{fruit}" }
# Each with object
fruits.each_with_object("") { |fruit, str| str << fruit[0] }
# => "abc"
# Cycle (repeat infinitely)
fruits.cycle(2) { |f| puts f }
# prints: apple, banana, cherry, apple, banana, cherry
Reducing to Single Value
numbers = [1, 2, 3, 4, 5]
# Sum all elements
numbers.sum
# => 15
# With initial value
numbers.sum(10)
# => 25
# Custom reduction
product = numbers.reduce(1) { |acc, n| acc * n }
# => 120
# Inject is alias for reduce
sum = numbers.inject(:+)
# => 15
Array Comparisons
Checking Equality
a = [1, 2, 3]
b = [1, 2, 3]
c = [1, 2, 4]
a == b # => true
a == c # => false
# Compare arrays element-by-element
a.zip(c).each { |x, y| puts "#{x} vs #{y}" }
Set Operations
a = [1, 2, 3, 4]
b = [3, 4, 5, 6]
# Intersection (common elements)
a & b
# => [3, 4]
# Union (all unique elements)
a | b
# => [1, 2, 3, 4, 5, 6]
# Difference
a - b
# => [1, 2]
b - a
# => [5, 6]
Common Pitfalls
Mutating During Iteration
Never modify the same array you’re iterating over:
# WRONG - unpredictable behavior
numbers = [1, 2, 3]
numbers.each { |n| numbers.delete(n) if n.odd? }
# => [2]
# CORRECT - work on a copy
numbers = [1, 2, 3]
numbers.dup.each { |n| numbers.delete(n) if n.odd? }
# => [2]
Reference vs Copy
Remember that assignment copies references, not objects:
# WRONG - both point to same array
original = [1, 2, 3]
copy = original
copy << 4
original # => [1, 2, 3, 4] - original modified!
# CORRECT - create a new array
original = [1, 2, 3]
copy = original.dup
# or: copy = original.clone
copy << 4
original # => [1, 2, 3]
Performance with Large Arrays
For large datasets, consider these tips:
# Use lazy for chainable enumerators
result = (1..1_000_000)
.lazy
.select { |n| n.even? }
.map { |n| n ** 2 }
.first(10)
# Avoid creating intermediate arrays with blocks
# Prefer:
array.select(&:positive?)
# Over:
array.select { |n| n.positive? }
See Also
Array#map— Transforming array elementsArray#select— Filtering arraysArray#reduce— Reducing arrays to single valueArray#sort— Sorting arraysArray#flatten— Handling nested arrays