Ruby Collections

Arrays

Creation and access
ports = [22, 80, 443, 8080, 8443]
hosts = %w[vault-01 ise-01 bind-01]     # word array
syms  = %i[active inactive degraded]    # symbol array

Array.new(5) { |i| i * 10 }             # => [0, 10, 20, 30, 40]
(1..10).to_a                             # => [1, 2, ..., 10]

ports[0]                                 # => 22
ports[-1]                                # => 8443
ports[1..3]                              # => [80, 443, 8080]
ports.first(2)                           # => [22, 80]
Array operations
ports << 9090                            # append
ports.unshift(21)                        # prepend
ports.pop                                # remove last
ports.delete(80)                         # remove by value

# Set operations
a = [1, 2, 3, 4]; b = [3, 4, 5, 6]
a | b                                    # union: [1, 2, 3, 4, 5, 6]
a & b                                    # intersection: [3, 4]
a - b                                    # difference: [1, 2]

[[1, 2], [3, [4]]].flatten               # => [1, 2, 3, 4]
[1, nil, 2, nil].compact                 # => [1, 2]
[1, 2, 2, 3].uniq                        # => [1, 2, 3]

Enumerable Methods

map, select, reject, reduce
ports = [22, 80, 443, 8080, 8443]

ports.map { |p| "#{p}/tcp" }             # transform
ports.select { |p| p > 1000 }           # => [8080, 8443]
ports.reject { |p| p > 1000 }           # => [22, 80, 443]
ports.filter_map { |p| p if p < 100 }   # => [22, 80]

ports.reduce(:+)                         # => 17068
ports.sum                                # => 17068
ports.minmax                             # => [22, 8443]
ports.count { |p| p > 100 }             # => 3

ports.group_by { |p| p > 1023 ? :high : :low }
# => { low: [22, 80, 443], high: [8080, 8443] }

ports.each_with_object({}) do |port, h|
  h[port] = port > 1023 ? "ephemeral" : "well-known"
end

Hashes

Creation and access
device = {
  hostname: "sw-core-01",
  ip: "10.50.1.2",
  vlans: [10, 20, 30],
  status: :active
}

device[:hostname]                        # => "sw-core-01"
device.fetch(:ip)                        # raises if missing
device.fetch(:location, "unknown")       # default
device.dig(:nested, :deep, :key)         # safe nested access

# Default values
counts = Hash.new(0)
counts["errors"] += 1                    # => 1

lists = Hash.new { |h, k| h[k] = [] }
lists["warnings"] << "timeout"
Hash operations
defaults = { timeout: 30, retries: 3 }
overrides = { timeout: 10, verbose: true }
config = defaults.merge(overrides)
# => { timeout: 10, retries: 3, verbose: true }

device.transform_keys(&:to_s)
device.select { |k, v| v.is_a?(String) }
device.slice(:hostname, :ip)             # Ruby 2.5+
device.except(:status)                   # Ruby 3.0+

hostname, ip = device.values_at(:hostname, :ip)

Ranges

Range patterns
(1..10)                                  # inclusive
(1...10)                                 # exclusive end
(1..1023).include?(443)                  # => true
(1..10).step(2).to_a                     # => [1, 3, 5, 7, 9]
(1..)                                    # endless range (Ruby 2.6+)