Ruby Arrays
Arrays are one of the most commonly used data structures in Ruby, used to store ordered collections of elements. Ruby arrays are powerful and flexible, can store elements of different types, and provide rich built-in methods for data manipulation. This chapter will introduce in detail the creation, manipulation, and processing methods of arrays in Ruby.
🎯 Array Basics
Array Definition
Ruby provides multiple ways to create arrays:
ruby
# Use literal syntax
fruits = ["Apple", "Banana", "Orange"]
numbers = [1, 2, 3, 4, 5]
mixed = ["String", 123, true, nil]
# Use Array.new method
empty_array = Array.new
sized_array = Array.new(3) # [nil, nil, nil]
initialized_array = Array.new(3, "default") # ["default", "default", "default"]
# Use %w shortcut to create string array
words = %w[hello world ruby programming]
# Equivalent to ["hello", "world", "ruby", "programming"]
# Use %i shortcut to create symbol array
symbols = %i[apple banana orange]
# Equivalent to [:apple, :banana, :orange]
# Use range to create array
range_array = (1..5).to_a # [1, 2, 3, 4, 5]
range_array2 = ("a".."e").to_a # ["a", "b", "c", "d", "e"]
# Create array from other objects
array_from_string = "hello".split("") # ["h", "e", "l", "l", "o"]
array_from_range = Array(1..3) # [1, 2, 3]Array Access
ruby
fruits = ["Apple", "Banana", "Orange", "Grape", "Strawberry"]
# Access elements by index
puts fruits[0] # Apple
puts fruits[2] # Orange
puts fruits[-1] # Strawberry (negative index starts from end)
puts fruits[-2] # Grape
# Access multiple elements by range
puts fruits[1..3].inspect # ["Banana", "Orange", "Grape"]
puts fruits[1...3].inspect # ["Banana", "Orange"] (doesn't include end index)
puts fruits[-3..-1].inspect # ["Orange", "Grape", "Strawberry"]
# Use at method for access
puts fruits.at(1) # Banana
# Get first and last elements
puts fruits.first # Apple
puts fruits.last # Strawberry
# Get first n or last n elements
puts fruits.first(3).inspect # ["Apple", "Banana", "Orange"]
puts fruits.last(2).inspect # ["Grape", "Strawberry"]
# Check if array contains an element
puts fruits.include?("Banana") # true
puts fruits.include?("Watermelon") # false📏 Array Properties
Array Length and Size
ruby
numbers = [1, 2, 3, 4, 5]
# Get array length
puts numbers.length # 5
puts numbers.size # 5 (alias for length)
# Check if array is empty
puts numbers.empty? # false
puts [].empty? # true
# Get array count information
puts numbers.count # 5
puts numbers.count(3) # 1 (count specific elements)
puts numbers.count { |n| n > 3 } # 2 (count elements satisfying condition)Array Comparison
ruby
arr1 = [1, 2, 3]
arr2 = [1, 2, 3]
arr3 = [3, 2, 1]
# Equality comparison
puts arr1 == arr2 # true
puts arr1 == arr3 # false
# Compare array contents (considering order)
puts arr1.eql?(arr2) # true
# Object identity comparison
puts arr1.equal?(arr2) # false (different objects)
puts arr1.equal?(arr1) # true (same object)
# Array comparison (lexicographical)
puts [1, 2, 3] <=> [1, 2, 3] # 0 (equal)
puts [1, 2, 3] <=> [1, 2, 4] # -1 (less than)
puts [1, 2, 4] <=> [1, 2, 3] # 1 (greater than)➕ Array Operations
Adding Elements
ruby
# Use push or << to add elements at the end
fruits = ["Apple", "Banana"]
fruits.push("Orange")
fruits << "Grape" # Shorthand form
puts fruits.inspect # ["Apple", "Banana", "Orange", "Grape"]
# Use unshift to add elements at the beginning
fruits.unshift("Strawberry")
puts fruits.inspect # ["Strawberry", "Apple", "Banana", "Orange", "Grape"]
# Insert elements at specified position
fruits.insert(2, "Mango", "Pear")
puts fruits.inspect # ["Strawberry", "Apple", "Mango", "Pear", "Banana", "Orange", "Grape"]
# Use concat to concatenate arrays
more_fruits = ["Cherry", "Peach"]
fruits.concat(more_fruits)
puts fruits.inspect # ["Strawberry", "Apple", "Mango", "Pear", "Banana", "Orange", "Grape", "Cherry", "Peach"]Deleting Elements
ruby
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Delete last element
last_element = numbers.pop
puts last_element # 10
puts numbers.inspect # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Delete first element
first_element = numbers.shift
puts first_element # 1
puts numbers.inspect # [2, 3, 4, 5, 6, 7, 8, 9]
# Delete element with specified value
numbers.delete(5)
puts numbers.inspect # [2, 3, 4, 6, 7, 8, 9]
# Delete element at specified index
deleted_element = numbers.delete_at(0)
puts deleted_element # 2
puts numbers.inspect # [3, 4, 6, 7, 8, 9]
# Delete elements satisfying condition
numbers.delete_if { |n| n > 7 }
puts numbers.inspect # [3, 4, 6, 7]
# Clear array
numbers.clear
puts numbers.inspect # []Modifying Elements
ruby
letters = ["a", "b", "c", "d", "e"]
# Modify single element by index
letters[0] = "A"
puts letters.inspect # ["A", "b", "c", "d", "e"]
# Modify multiple elements by range
letters[1..2] = ["B", "C"]
puts letters.inspect # ["A", "B", "C", "d", "e"]
# Use fill to fill elements
numbers = [1, 2, 3, 4, 5]
numbers.fill(0, 2, 2) # Start at index 2, fill 2 elements with 0
puts numbers.inspect # [1, 2, 0, 0, 5]
# Use fill to fill entire array
empty_array = [nil, nil, nil]
empty_array.fill("default")
puts empty_array.inspect # ["default", "default", "default"]🔍 Array Search and Filter
Finding Elements
ruby
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Find first element satisfying condition
even_number = numbers.find { |n| n.even? }
puts even_number # 2
# Find all elements satisfying condition
even_numbers = numbers.select { |n| n.even? }
puts even_numbers.inspect # [2, 4, 6, 8, 10]
# Find elements not satisfying condition
odd_numbers = numbers.reject { |n| n.even? }
puts odd_numbers.inspect # [1, 3, 5, 7, 9]
# Find element index
index = numbers.index(5)
puts index # 4
# Find index of element satisfying condition
index = numbers.index { |n| n > 5 }
puts index # 5 (index of first element greater than 5)Array Filtering and Grouping
ruby
# Use take and drop
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
puts numbers.take(3).inspect # [1, 2, 3] (take first 3)
puts numbers.drop(3).inspect # [4, 5, 6, 7, 8, 9, 10] (skip first 3)
# Use take_while and drop_while
puts numbers.take_while { |n| n < 5 }.inspect # [1, 2, 3, 4]
puts numbers.drop_while { |n| n < 5 }.inspect # [5, 6, 7, 8, 9, 10]
# Grouping
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
grouped = numbers.group_by { |n| n.even? ? "Even" : "Odd" }
puts grouped
# {"Odd"=>[1, 3, 5, 7, 9], "Even"=>[2, 4, 6, 8, 10]}
# Chunking
data = [1, 2, 3, 4, 5, 6, 7, 8]
chunks = data.each_slice(3).to_a
puts chunks.inspect # [[1, 2, 3], [4, 5, 6], [7, 8]]
# Partitioning
partitioned = numbers.partition { |n| n.even? }
puts partitioned.inspect # [[2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]🔧 Array Transformation
Mapping and Conversion
ruby
numbers = [1, 2, 3, 4, 5]
# Use map to transform each element
squared = numbers.map { |n| n * n }
puts squared.inspect # [1, 4, 9, 16, 25]
# Use collect (alias for map)
doubled = numbers.collect { |n| n * 2 }
puts doubled.inspect # [2, 4, 6, 8, 10]
# In-place modification (use map!)
numbers.map! { |n| n * 2 }
puts numbers.inspect # [2, 4, 6, 8, 10]
# Flatten nested arrays
nested = [[1, 2], [3, 4], [5, 6]]
flattened = nested.flatten
puts flattened.inspect # [1, 2, 3, 4, 5, 6]
# Deep flatten
deep_nested = [1, [2, [3, 4]], 5]
deep_flattened = deep_nested.flatten(1) # Flatten only one level
puts deep_flattened.inspect # [1, 2, [3, 4], 5]Sorting and Reversing
ruby
# Number sorting
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_asc = numbers.sort
puts sorted_asc.inspect # [1, 1, 2, 3, 4, 5, 6, 9]
sorted_desc = numbers.sort { |a, b| b <=> a }
puts sorted_desc.inspect # [9, 6, 5, 4, 3, 2, 1, 1]
# Use sort_by to sort by specific condition
words = ["apple", "banana", "cherry", "date"]
sorted_by_length = words.sort_by { |word| word.length }
puts sorted_by_length.inspect # ["date", "apple", "cherry", "banana"]
# Reverse array
reversed = numbers.reverse
puts reversed.inspect # [6, 2, 9, 5, 1, 4, 1, 3]
# Reverse in-place
numbers.reverse!
puts numbers.inspect # [6, 2, 9, 5, 1, 4, 1, 3]
# Remove duplicate elements
duplicates = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique = duplicates.uniq
puts unique.inspect # [1, 2, 3, 4]
# Remove duplicates by condition
people = [
{name: "Zhang San", age: 25},
{name: "Li Si", age: 30},
{name: "Zhang San", age: 28}
]
unique_by_name = people.uniq { |person| person[:name] }
puts unique_by_name.inspect
# [{:name=>"Zhang San", :age=>25}, {:name=>"Li Si", :age=>30}]🔁 Array Iteration
Basic Iteration
ruby
fruits = ["Apple", "Banana", "Orange"]
# Use each to traverse
fruits.each { |fruit| puts "I like to eat #{fruit}" }
# I like to eat Apple
# I like to eat Banana
# I like to eat Orange
# Use each_with_index to get index
fruits.each_with_index do |fruit, index|
puts "#{index + 1}. #{fruit}"
end
# 1. Apple
# 2. Banana
# 3. Orange
# Use reverse_each for reverse traversal
fruits.reverse_each { |fruit| puts fruit }
# Orange
# Banana
# AppleAdvanced Iteration
ruby
numbers = [1, 2, 3, 4, 5]
# Use map for transformation
squared = numbers.map { |n| n ** 2 }
puts squared.inspect # [1, 4, 9, 16, 25]
# Use each_with_object to accumulate results
sum = numbers.each_with_object(0) { |n, total| total += n }
puts sum # 15
# Use reduce/inject for accumulation
sum = numbers.reduce(0) { |total, n| total + n }
puts sum # 15
product = numbers.reduce(1) { |total, n| total * n }
puts product # 120
# Use reduce shorthand
sum = numbers.reduce(:+)
product = numbers.reduce(:*)
# Use zip to merge arrays
letters = ["a", "b", "c"]
numbers = [1, 2, 3]
combined = letters.zip(numbers)
puts combined.inspect # [["a", 1], ["b", 2], ["c", 3]]
# Use transpose to transpose array
matrix = [[1, 2, 3], [4, 5, 6]]
transposed = matrix.transpose
puts transposed.inspect # [[1, 4], [2, 5], [3, 6]]🎯 Array Practice Examples
Data Processing Pipeline
ruby
class DataProcessor
def initialize(data)
@data = data
end
# Chained method calls
def filter(&block)
DataProcessor.new(@data.select(&block))
end
def map(&block)
DataProcessor.new(@data.map(&block))
end
def sort(&block)
DataProcessor.new(@data.sort(&block))
end
def take(n)
DataProcessor.new(@data.take(n))
end
def result
@data
end
end
# Use data processing pipeline
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result = DataProcessor.new(numbers)
.filter { |n| n.even? }
.map { |n| n ** 2 }
.sort { |a, b| b <=> a }
.take(3)
.result
puts result.inspect # [100, 64, 36]Array Statistical Analysis
ruby
class ArrayStatistics
def initialize(array)
@array = array
end
# Calculate mean
def mean
return 0 if @array.empty?
@array.sum.to_f / @array.length
end
# Calculate median
def median
return nil if @array.empty?
sorted = @array.sort
length = sorted.length
if length.odd?
sorted[length / 2]
else
(sorted[length / 2 - 1] + sorted[length / 2]) / 2.0
end
end
# Calculate mode
def mode
return nil if @array.empty?
frequency = Hash.new(0)
@array.each { |n| frequency[n] += 1 }
max_frequency = frequency.values.max
frequency.select { |k, v| v == max_frequency }.keys
end
# Calculate variance
def variance
return 0 if @array.empty?
avg = mean
sum = @array.reduce(0) { |total, n| total + (n - avg) ** 2 }
sum / @array.length
end
# Calculate standard deviation
def standard_deviation
Math.sqrt(variance)
end
# Get statistical summary
def summary
{
count: @array.length,
mean: mean,
median: median,
mode: mode,
min: @array.min,
max: @array.max,
range: @array.max - @array.min,
variance: variance,
standard_deviation: standard_deviation
}
end
end
# Use statistical analysis
data = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8, 9]
stats = ArrayStatistics.new(data)
puts stats.summary
# {:count=>12, :mean=>4.75, :median=>5.0, :mode=>[5], :min=>1, :max=>9, :range=>8, :variance=>5.6875, :standard_deviation=>2.384842971765449}Array Paginator
ruby
class ArrayPaginator
def initialize(array, per_page = 10)
@array = array
@per_page = per_page
end
# Get total pages
def total_pages
(@array.length.to_f / @per_page).ceil
end
# Get data for specified page
def page(page_number)
return [] if page_number < 1 || page_number > total_pages
start_index = (page_number - 1) * @per_page
end_index = start_index + @per_page - 1
@array[start_index..end_index]
end
# Check if has next page
def has_next_page?(current_page)
current_page < total_pages
end
# Check if has previous page
def has_prev_page?(current_page)
current_page > 1
end
# Get next page
def next_page(current_page)
current_page + 1 if has_next_page?(current_page)
end
# Get previous page
def prev_page(current_page)
current_page - 1 if has_prev_page?(current_page)
end
end
# Use paginator
data = (1..100).to_a
paginator = ArrayPaginator.new(data, 10)
puts "Total pages: #{paginator.total_pages}" # Total pages: 10
puts "Page 1: #{paginator.page(1).inspect}" # Page 1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
puts "Page 5: #{paginator.page(5).inspect}" # Page 5: [41, 42, 43, 44, 45, 46, 47, 48, 49, 50]
puts "Has next page(5): #{paginator.has_next_page?(5)}" # Has next page(5): true
puts "Next page(5): #{paginator.next_page(5)}" # Next page(5): 6📚 Next Steps
After mastering Ruby array operations, it is recommended to continue learning:
- Ruby Hashes - Learn key-value pair data structure
- Ruby Ranges - Master range object usage
- Ruby Iterators - Deep dive into iteration patterns
- Ruby Blocks and Modules - Learn code blocks and modular programming
Continue your Ruby learning journey!