Ruby Arrays — Complete Guide with Methods map select reduce and sort
In this tutorial, you will learn about Ruby Arrays. We cover key concepts, practical examples, and best practices to help you master this topic.
Ruby arrays are ordered, integer-indexed collections that can hold any object type, with powerful built-in methods like map, select, reduce, and sort for expressive data transformation.
What You'll Learn
- Creating and accessing Ruby arrays
- All major array methods: push, pop, shift, unshift, map, select, reduce
- Sorting and searching arrays
- Array transformations and combinations
Why It Matters
Arrays are the foundation of data processing in Ruby. Durga Antivirus Pro uses arrays to store file paths, scan results, and threat signatures. The ability to map, filter, and reduce arrays efficiently determines how well your code processes real-world data. Mastering array methods eliminates most manual loop writing in daily Ruby work.
Real-World Use
A Rails application might use map to extract usernames from a collection of user objects, select to find active subscriptions, and reduce to calculate totals from invoice items. A data pipeline uses sort to order records and uniq to deduplicate entries.
flowchart LR
A["Arrays"] --> B["Creation & Access"]
B --> C["Basic Methods"]
C --> D["Transformations"]
D --> E["Sorting & Search"]
E --> F["Hashes"]
A:::current --> B
style A fill:#2563eb,stroke:#2563eb,color:#fff
style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
style E fill:#dbeafe,stroke:#2563eb,color:#1e40af
style F fill:#f1f5f9,stroke:#94a3b8,color:#64748b
Creating Arrays
# Empty array
arr = []
arr = Array.new
# With initial values
arr = [1, 2, 3]
# With Array.new
arr = Array.new(3) # [nil, nil, nil]
arr = Array.new(3, "a") # ["a", "a", "a"]
arr = Array.new(3) { |i| i * 2 } # [0, 2, 4]
# Using %w for string arrays
words = %w[apple banana cherry]
# ["apple", "banana", "cherry"]
# Using %i for symbol arrays
symbols = %i[red green blue]
# [:red, :green, :blue]
Accessing Elements
arr = [10, 20, 30, 40, 50]
# By index
puts arr[0] # 10
puts arr[-1] # 50 (last element)
puts arr[-2] # 40
# By range
puts arr[1..3].inspect # [20, 30, 40]
puts arr[1, 3].inspect # [20, 30, 40] (start, length)
# First and last
puts arr.first # 10
puts arr.last # 50
puts arr.first(3).inspect # [10, 20, 30]
# Fetch with default
puts arr.fetch(0) # 10
puts arr.fetch(10, "default") # "default"
# arr.fetch(10) # IndexError!
Adding and Removing Elements
arr = [1, 2, 3]
# Add to end
arr.push(4) # [1, 2, 3, 4]
arr << 5 # [1, 2, 3, 4, 5]
# Add to beginning
arr.unshift(0) # [0, 1, 2, 3, 4, 5]
# Insert at position
arr.insert(3, "inserted") # [0, 1, 2, "inserted", 3, 4, 5]
# Remove from end
arr.pop # 5
# Remove from beginning
arr.shift # 0
# Remove specific value
arr.delete(1) # removes 1
# Remove at index
arr.delete_at(1) # removes element at index 1
# Remove duplicates
[1, 2, 2, 3].uniq # [1, 2, 3]
Array Transformation Methods
Map (Collect)
Transforms each element and returns a new array:
numbers = [1, 2, 3, 4, 5]
doubled = numbers.map { |n| n * 2 }
puts doubled.inspect
# [2, 4, 6, 8, 10]
# With index
numbers.map.with_index { |n, i| n * i }
# [0, 2, 6, 12, 20]
Select (Filter)
Returns elements where the block evaluates to truthy:
numbers = [1, 2, 3, 4, 5, 6]
even = numbers.select { |n| n.even? }
puts even.inspect
# [2, 4, 6]
# Multiple conditions
result = numbers.select { |n| n > 2 && n.even? }
puts result.inspect
# [4, 6]
Reject
Opposite of select — excludes elements where block is truthy:
numbers = [1, 2, 3, 4, 5]
odds = numbers.reject { |n| n.even? }
# [1, 3, 5]
Reduce (Inject)
Accumulates values across elements:
numbers = [1, 2, 3, 4, 5]
# Sum
sum = numbers.reduce(0) { |acc, n| acc + n }
puts sum # 15
# Shorter form
sum = numbers.reduce(:+)
puts sum # 15
# Product
product = numbers.reduce(1, :*)
puts product # 120
# Building a hash
words = %w[cat dog bird]
lengths = words.reduce({}) { |hash, word| hash[word] = word.length; hash }
puts lengths.inspect
# {"cat"=>3, "dog"=>3, "bird"=>4}
Flatten
Nested arrays to single-level:
nested = [1, [2, 3], [[4, 5], 6]]
puts nested.flatten.inspect
# [1, 2, 3, 4, 5, 6]
# With depth limit
puts nested.flatten(1).inspect
# [1, 2, 3, [4, 5], 6]
Sorting Arrays
numbers = [3, 1, 4, 1, 5, 9]
# Ascending
puts numbers.sort.inspect
# [1, 1, 3, 4, 5, 9]
# Descending
puts numbers.sort.reverse.inspect
# [9, 5, 4, 3, 1, 1]
# With block
puts numbers.sort { |a, b| b <=> a }.inspect
# [9, 5, 4, 3, 1, 1]
# Sort by
words = %w[apple banana cherry date]
puts words.sort_by { |w| w.length }.inspect
# ["date", "apple", "banana", "cherry"]
Searching Arrays
arr = [10, 20, 30, 20, 40]
# Find first match
puts arr.find { |n| n > 25 } # 30
# Find all matches
puts arr.find_all { |n| n > 25 }.inspect
# [30, 40]
# Any?
puts arr.any? { |n| n > 30 } # true
puts arr.any? { |n| n > 50 } # false
# All?
puts arr.all? { |n| n > 5 } # true
# Include?
puts arr.include?(20) # true
puts arr.include?(99) # false
# Count
puts arr.count # 5
puts arr.count(20) # 2
puts arr.count { |n| n > 20 } # 2
Array Mathematical Operations
a = [1, 2, 3]
b = [3, 4, 5]
# Union
puts (a | b).inspect # [1, 2, 3, 4, 5]
# Intersection
puts (a & b).inspect # [3]
# Difference
puts (a - b).inspect # [1, 2]
puts (b - a).inspect # [4, 5]
# Concatenation
puts (a + b).inspect # [1, 2, 3, 3, 4, 5]
# Multiplication
puts a * 2 # [1, 2, 3, 1, 2, 3]
Array as Stack and Queue
# Stack (LIFO)
stack = []
stack.push(1)
stack.push(2)
stack.push(3)
puts stack.pop # 3
puts stack.pop # 2
# Queue (FIFO)
queue = []
queue.push(1)
queue.push(2)
queue.push(3)
puts queue.shift # 1
puts queue.shift # 2
Common Array Idioms
# Joining elements
puts [1, 2, 3].join(", ") # "1, 2, 3"
# Sample random element
[1, 2, 3].sample # random element
# Shuffle
[1, 2, 3].shuffle # [2, 1, 3] (random order)
# Chunk
[1, 2, 3, 4, 5].each_slice(2) { |slice| puts slice.inspect }
# [1, 2]
# [3, 4]
# [5]
# Combination
[1, 2, 3].combination(2).to_a
# [[1, 2], [1, 3], [2, 3]]
# Permutation
[1, 2, 3].permutation(2).to_a
# [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
Converting Arrays
# Array to string
[1, 2, 3].to_s # "[1, 2, 3]"
# Array to hash
arr = [[:a, 1], [:b, 2]]
puts arr.to_h.inspect # {:a=>1, :b=>2}
# Flatten and uniq
[[1, 2], [2, 3]].flatten.uniq # [1, 2, 3]
# Compact (remove nil)
[1, nil, 2, nil, 3].compact # [1, 2, 3]
Common Mistakes
1. Confusing map and each
# each returns original array (for side effects)
result = [1, 2, 3].each { |n| n * 2 }
puts result.inspect # [1, 2, 3] — not transformed!
# map returns new array with transformed values
result = [1, 2, 3].map { |n| n * 2 }
puts result.inspect # [2, 4, 6]
2. Using shift on an Empty Array
arr = []
puts arr.shift # nil (no error)
# Always check first: unless arr.empty?
3. Modifying Array While Iterating
# Wrong
arr = [1, 2, 3, 4]
arr.each { |n| arr.delete(n) if n.even? }
# Right — iterate over copy
arr.dup.each { |n| arr.delete(n) if n.even? }
4. Forgetting Zero-Based Indexing
arr = [10, 20, 30]
puts arr[1] # 20, not 10!
5. Using == for Array Comparison
# This actually works correctly in Ruby
puts [1, 2, 3] == [1, 2, 3] # true
puts [1, 2, 3] == [1, 2, 4] # false
6. Forgetting That Arrays Can Hold Mixed Types
mixed = [1, "two", :three, [4], { five: 5 }]
puts mixed.inspect
# [1, "two", :three, [4], {:five=>5}]
Practice Questions
1. What's the difference between map and select?
map transforms every element and returns a new array of the same length. select filters elements and returns a potentially shorter array containing only elements for which the block returned truthy.
2. How do you remove duplicate elements from an array?
Use .uniq which returns a new array without duplicates. Use .uniq! to modify in place.
3. What does reduce do?
reduce (aliased as inject) accumulates a value across all elements. With an initial value, it passes that accumulator and each element to the block, returning the final accumulator.
4. How do you check if an element exists in an array?
Use .include?(value), .any? { |e| condition }, or .find { |e| condition }.
Challenge: Write a method that takes an array of numbers and returns a hash with keys :evens and :odds, each containing arrays of the respective numbers sorted in descending order.
Solution
def partition_numbers(numbers)
{
evens: numbers.select(&:even?).sort.reverse,
odds: numbers.select(&:odd?).sort.reverse
}
end
result = partition_numbers([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
puts result.inspect
# {:evens=>[10, 8, 6, 4, 2], :odds=>[9, 7, 5, 3, 1]}
FAQ
{{< faq question="What's the maximum size of a Ruby array?" >}} Ruby arrays are limited only by available memory. A 64-bit system can hold arrays with millions of elements before hitting memory constraints. Array operations scale linearly with size. {{< /faq >}}
{{< faq question="When should I use an array vs a hash?" >}} Use arrays for ordered, integer-indexed collections. Use hashes for key-value pairs where you need fast lookup by a named key. Arrays excel at lists, queues, stacks, and sequences. {{< /faq >}}
{{< faq question="How do I create an array of specific length with default values?" >}}
Use Array.new(length, default) for identical values, or Array.new(length) { |i| expression } for computed values. The block form is recommended because Array.new(3, 'a') creates a single object referenced three times.
{{< /faq >}}
{{< faq question="What's the difference between delete and delete_at?" >}}
delete(value) removes all occurrences of a specific value. delete_at(index) removes the element at a specific index position.
{{< /faq >}}
{{< faq question="Can arrays have negative indices?" >}}
Yes. Negative indices count from the end of the array. arr[-1] is the last element, arr[-2] is the second-to-last, and so on.
{{< /faq >}}
Try It Yourself
# array_demo.rb
data = [3, 7, 2, 9, 1, 5, 8, 4, 6, 10]
puts "Original: #{data.inspect}"
puts "Sorted: #{data.sort.inspect}"
puts "Evens: #{data.select(&:even?).inspect}"
puts "Doubled: #{data.map { |n| n * 2 }.inspect}"
puts "Sum: #{data.reduce(:+)}"
puts "First 3: #{data.first(3).inspect}"
puts "Last 3: #{data.last(3).inspect}"
puts "Sample: #{data.sample(2).inspect}"
puts "Chunks of 3:"
data.each_slice(3) { |slice| puts " #{slice.inspect}" }
Expected output:
Original: [3, 7, 2, 9, 1, 5, 8, 4, 6, 10]
Sorted: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Evens: [2, 8, 4, 6, 10]
Doubled: [6, 14, 4, 18, 2, 10, 16, 8, 12, 20]
Sum: 55
First 3: [3, 7, 2]
Last 3: [4, 6, 10]
Sample: [5, 9] (may vary)
Chunks of 3:
[3, 7, 2]
[9, 1, 5]
[8, 4, 6]
[10]
What's Next
Now that you understand arrays, learn about hashes — Ruby's key-value data structure for storing and retrieving data by named keys.
| Topic | Description | Link |
|---|---|---|
| Ruby Hashes | Hash syntax, symbol keys, fetch, merge | {{< ref "07-hashes" >}} |
| Ruby Methods | def, return, splat, keyword args | {{< ref "08-methods" >}} |
| Python Lists | Compare Python list comprehensions | Python |
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro