rubyguides

Array

Array.new, []

The Array class is Ruby’s primary ordered collection. Arrays can hold objects of any type and grow dynamically. They are one of the most frequently used data structures.

Creating Arrays

# Literal syntax
arr = [1, 2, 3]
arr = []  # Empty array

# With Array.new
arr = Array.new(3)        # => [nil, nil, nil]
arr = Array.new(3, 0)     # => [0, 0, 0]
arr = Array.new(3) { |i| i }  # => [0, 1, 2]

# From other objects
Array("hello")  # => ["hello"]
Array(1..5)     # => [1, 2, 3, 4, 5]

The literal syntax [1, 2, 3] is the most common way to create an array, but Array.new with a block gives you control over each element’s initial value. The Array() conversion method turns ranges and other enumerables into arrays.

Accessing Elements

arr = [:a, :b, :c, :d]

arr[0]     # => :a — first
arr[-1]    # => :d — last
arr[1, 2]  # => [:b, :c] — slice
arr.first  # => :a
arr.last   # => :d

Positive indices count from the start, negative indices count from the end. The two-argument form arr[start, length] returns a slice as a new array. These access patterns cover nearly every read operation you will need on an ordered collection.

Modification

arr = [1, 2, 3]

arr << 4        # => [1, 2, 3, 4] — push
arr.push(5)     # => [1, 2, 3, 4, 5]
arr.pop         # => 5, arr is [1, 2, 3, 4]
arr.shift       # => 1, arr is [2, 3, 4]
arr.unshift(0)  # => [0, 1, 2, 3, 4]

push and << add to the end, pop removes from the end, shift removes from the front, and unshift adds to the front. Together they let you use an array as a stack or a queue. All four methods mutate the array in place.

Iteration

[1, 2, 3].each { |i| puts i }
[1, 2, 3].map { |i| i * 2 }     # => [2, 4, 6]
[1, 2, 3].select { |i| i > 1 } # => [2, 3]
[1, 2, 3].reduce(:+)            # => 6

each is the foundation — it yields each element. map transforms, select filters, and reduce combines. These four cover most iteration patterns in day-to-day Ruby code.

Useful Methods

arr = [1, 2, 3, 2, 1]

arr.length      # => 5
arr.size        # => 5
arr.empty?      # => false
arr.include?(2) # => true
arr.index(2)    # => 1
arr.count(2)    # => 2
arr.uniq        # => [1, 2, 3]
arr.sort        # => [1, 1, 2, 2, 3]
arr.reverse     # => [1, 2, 3, 2, 1]

length, size, and count give the number of elements. uniq removes duplicates, sort orders them, and reverse flips the order. These are the bread-and-butter methods for everyday array work, and knowing them well saves time.

Practical Examples

Queue

queue = []
queue << item
item = queue.shift

A queue is first-in-first-out: push adds to the back and shift removes from the front. This pattern is useful for job queues, event processing, and breadth-first searches. The array grows and shrinks as items come and go.

Stack

stack = []
stack.push(item)
item = stack.pop

A stack is last-in-first-out: push adds to the top and pop removes from the top. This pattern works for undo stacks, expression evaluation, and depth-first traversals. Both push and pop operate on the end of the array.

Set-like Operations

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

a | b   # => [1, 2, 3, 4] — union
a & b   # => [2, 3] — intersection
a - b   # => [1] — difference

The union, intersection, and difference operators treat arrays as sets. They preserve order from the left operand and remove duplicates. For larger datasets, Ruby’s Set class from the standard library is more efficient.

Matrix Representation

matrix = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
]

matrix[1][1]  # => 5 — center

Nested arrays work as a lightweight matrix. Access is matrix[row][col], with both indices zero-based. For heavy numeric work, consider a dedicated matrix library like the Matrix class in Ruby’s standard library.

Comprehension-style

# Like list comprehension in Python
arr = (1..5).to_a.select { |x| x.even? }  # => [2, 4]
squares = (1..5).map { |x| x*x }           # => [1, 4, 9, 16, 25]

Arrays are versatile, efficient for indexed access, and form the foundation of many Ruby programs.

Why arrays stay useful

Arrays are still the default choice when order matters and you want direct access by position. They work well for lists, queues, stacks, and any data that naturally stays in sequence. Because arrays can hold mixed types, they are flexible enough for quick scripts and small data transformations, but that flexibility also means the code should be clear about what each position represents. If the data is really key-value shaped, a hash is usually the better fit. When the order is part of the meaning, an array keeps the intent simple.

Arrays are also a good choice when you want a short, predictable API for common collection work. Methods like push, pop, shift, map, and select cover a lot of everyday tasks without making the code feel heavyweight. That is why arrays remain the default container for ordered data in Ruby: they fit a wide range of problems without forcing you into a more specialized structure too early. When the shape is obvious, later readers can follow the code without needing extra explanation.

If the array starts to hold too many different kinds of values, that is usually a clue that the data wants a different shape. A hash, a small object, or a named struct can make the meaning clearer when position alone is not enough. Arrays are strongest when order is the main idea and the surrounding code can keep the meaning of each slot simple.

That balance is what makes arrays feel so natural in Ruby code. They are easy to build, easy to inspect, and easy to pass around, which is why they work well for a lot of everyday collection tasks. When the list is really a list, an array keeps the code direct and the intent easy to follow.

See Also