Ruby Arrays
Ruby Arrays: Ordered Collections
Section titled “Ruby Arrays: Ordered Collections”Ruby arrays are versatile, ordered collections that can hold objects of any type, including numbers, strings, hashes, or even other arrays. Each element in an array is accessed via an integer-based index.
Array indexing starts at 0, similar to languages like C or Java. Negative indices count from the end of the array: -1 refers to the last element, -2 to the second-to-last, and so on. Ruby arrays are dynamic, meaning they automatically grow or shrink as you add or remove elements.
Creating Arrays:
Section titled “Creating Arrays:”The most common way to create an array is using array literal syntax []:
# An empty arrayempty_array = []
# An array of numbersnumbers = [1, 2, 3, 4, 5]
# An array of mixed typesmixed_array = [1, "hello", :symbol, ["nested", "array"]]You can also use the Array.new class method:
# Creates an empty arraynames = Array.new
# Creates an array with a predefined size (20 elements, all nil)names_with_size = Array.new(20)
# Returns the size (or length) of an arrayputs names_with_size.size # Output: 20puts names_with_size.length # Output: 20You can initialize an array with a default value for all elements:
#!/usr/bin/ruby
default_values_array = Array.new(4, "default")puts default_values_array.inspect # Output: ["default", "default", "default", "default"]Be cautious when initializing with mutable objects. All elements will reference the same object:
#!/usr/bin/ruby
# INCORRECT way if you want distinct mutable objectsarray_of_hashes = Array.new(3, {})array_of_hashes[0][:name] = "Alice"puts array_of_hashes.inspect # Output: [{:name=>"Alice"}, {:name=>"Alice"}, {:name=>"Alice"}]
# CORRECT way using a block for distinct mutable objectsdistinct_hashes_array = Array.new(3) { {} }distinct_hashes_array[0][:name] = "Alice"puts distinct_hashes_array.inspect # Output: [{:name=>"Alice"}, {}, {}]You can also use a block with new to populate each element dynamically:
#!/usr/bin/ruby
squares = Array.new(5) { |index| index * index }puts squares.inspect # Output: [0, 1, 4, 9, 16]Other ways to create arrays include Array.[] or the Kernel#Array method:
nums1 = Array.[](1, 2, 3, 4, 5)nums2 = Array[1, 2, 3, 4, 5]
# Using Kernel#Array with a rangedigits = Array(0..9)puts digits.inspect # Output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]Array Built-in Methods:
Section titled “Array Built-in Methods:”Arrays come with a rich set of built-in methods for manipulation, iteration, and querying. Here’s an example:
#!/usr/bin/ruby
digits = Array(0..9) # Creates [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
element_at_index_6 = digits.at(6)puts "Element at index 6: #{element_at_index_6}" # Output: Element at index 6: 6
first_three = digits.first(3)puts "First three elements: #{first_three.inspect}" # Output: First three elements: [0, 1, 2]
digits.push(10) # Adds 10 to the endputs "After push(10): #{digits.inspect}" # Output: After push(10): [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
last_element = digits.pop # Removes and returns the last elementputs "Popped element: #{last_element}" # Output: Popped element: 10puts "After pop: #{digits.inspect}" # Output: After pop: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]Below is a table of commonly used public array methods (assuming array is an Array object). For a complete list, always refer to the official Ruby documentation.
| No. | Methods with Description |
|---|---|
| 1 | array & other_array (Intersection)Returns a new array containing elements common to both arrays, with no duplicates. array.intersection(other_array) is an alias. |
| 2 | array * int (Repetition) or array * str (Join)If int is an integer, returns a new array built by concatenating int copies of array. If str is a string, equivalent to self.join(str). |
| 3 | array + other_array (Concatenation)Returns a new array by concatenating the two arrays. Does not modify the original arrays. |
| 4 | array - other_array (Difference)Returns a new array that is a copy of the original array, removing any items that also appear in other_array. array.difference(other_array) is an alias. |
| 5 | array <=> other_array (Comparison)Compares two arrays element by element. Returns -1, 0, or 1 if array is less than, equal to, or greater than other_array respectively. |
| 6 | array | other_array (Union)Returns a new array by joining array with other_array, removing duplicates. array.union(other_array) is an alias. |
| 7 | array << obj (Append/Shovel)Pushes the given object obj onto the end of array. Modifies array in place and returns array itself, allowing for chained appends. |
| 8 | array == other_array (Equality)Returns true if both arrays contain the same number of elements and each corresponding element is equal (using ==). |
| 9 | array[index], array[start, length], array[range], array.slice(...) (Element Access/Slicing)Returns an element or a subarray. Negative indices count from the end. Returns nil if the index is out of range. |
| 10 | array[index] = obj, array[start, length] = new_subarray, array[range] = new_subarray (Element Assignment)Assigns new values to elements or replaces subarrays. The array grows automatically if indices are out of bounds. |
| 11 | array.at(index)Returns the element at index. A negative index counts from the end. Returns nil if the index is out of range. |
| 12 | array.clearRemoves all elements from array, making it empty. Modifies array in place. |
| 13 | array.collect { |item| block } or array.map { |item| block } (Transformation)Invokes block once for each element of array. Creates a new array containing the values returned by the block. Does not modify the original array. |
| 14 | array.collect! { |item| block } or array.map! { |item| block } (In-place Transformation)Invokes block once for each element of array, replacing the element with the value returned by block. Modifies array in place. |
| 15 | array.compactReturns a new array with all nil elements removed. Does not modify the original array. |
| 16 | array.compact!Removes nil elements from array in place. Returns nil if no changes were made. |
| 17 | array.concat(other_array, ...)Appends the elements of other_array(s) to array. Modifies array in place. |
| 18 | array.delete(obj) { |obj| block }Deletes all items from array that are equal to obj. If an optional block is given, it’s executed if obj is not found. Modifies array in place. |
| 19 | array.delete_at(index)Deletes the element at the specified index, returning that element, or nil if the index is out of range. Modifies array in place. |
| 20 | array.delete_if { |item| block } or array.reject! { |item| block }Deletes every element of array for which block evaluates to true. Modifies array in place. |
| 21 | array.each { |item| block } (Iteration)Calls block once for each element in array, passing that element as a parameter. This is one of the most common ways to iterate over an array. |
| 22 | array.each_index { |index| block }Same as Array#each, but passes the index of the element instead of the element itself. |
| 23 | array.empty?Returns true if array contains no elements, false otherwise. |
| 24 | array.fetch(index), array.fetch(index, default), array.fetch(index) { |index| block }Returns the element at index. If index is out of bounds, raises an IndexError, returns default, or executes the block, depending on the form used. |
| 25 | array.fill(obj), array.fill(obj, start [, length]), array.fill(obj, range), or with a blockSets selected elements of array to obj or to the result of a block. Modifies array in place. |
| 26 | array.first or array.first(n)Returns the first element, or the first n elements, of array. If array is empty, the first form returns nil, and the second form returns an empty array. |
| 27 | array.flattenReturns a new array that is a one-dimensional flattening of array (recursively). |
| 28 | array.flatten!Flattens array in place. Returns nil if no modifications were made (i.e., array contains no subarrays). |
| 29 | array.include?(obj)Returns true if obj is present in array (checked using ==), false otherwise. |
| 30 | array.index(obj) or array.find_index(obj)Returns the index of the first element in array that is == to obj. Returns nil if no match is found. |
| 31 | array.insert(index, obj...)Inserts the given obj(s) before the element at the given index. Modifies array in place. |
| 32 | array.join(separator = $,)Returns a string created by converting each element of array to a string, separated by separator (default is an empty string if $, is nil). |
| 33 | array.last or array.last(n)Returns the last element(s) of array. If array is empty, the first form returns nil. |
| 34 | array.length or array.sizeReturns the number of elements in array. |
| 35 | array.pop(n=1)Removes the last n element(s) from array and returns them (or the single element if n=1). Returns nil or an empty array if array is empty. Modifies array in place. |
| 36 | array.push(obj, ...) or array.append(obj, ...)Appends the given obj(s) onto the end of array. Modifies array in place and returns array itself. |
| 37 | array.reject { |item| block }Returns a new array containing items from array for which the block is false. Does not modify original array. |
| 38 | array.reverseReturns a new array containing array’s elements in reverse order. |
| 39 | array.reverse!Reverses array in place. |
| 40 | array.select { |item| block } or array.filter { |item| block } (Filtering)Invokes the block for each element. Returns a new array containing those elements for which block returns a true value. |
| 41 | array.select! { |item| block } or array.filter! { |item| block } (In-place Filtering)Deletes elements from array for which the block is false. Modifies array in place. |
| 42 | array.shift(n=1)Removes the first n element(s) from array and returns them. Modifies array in place. |
| 43 | array.sort or array.sort { |a, b| block }Returns a new array created by sorting array. The block, if given, should implement a comparison between a and b (returning -1, 0, or 1). |
| 44 | array.sort! or array.sort! { |a, b| block }Sorts array in place. |
| 45 | array.uniqReturns a new array by removing duplicate values from array. |
| 46 | array.uniq!Removes duplicate elements from array in place. Returns nil if no changes are made. |
| 47 | array.unshift(obj, ...) or array.prepend(obj, ...)Prepends obj(s) to the front of array, shifting other elements up. Modifies array in place. |
| 48 | array.values_at(selector, ...)Returns an array containing elements from array corresponding to the given selector(s) (integer indices or ranges). |
| 49 | array.zip(other_array1, ...)Converts arguments to arrays, then merges elements of array with corresponding elements from each argument. It produces an array of arrays. |
The Array#pack Method and Directives:
Section titled “The Array#pack Method and Directives:”The pack method is a powerful tool for converting an array into a binary string sequence based on a template string. This is often used for creating data in specific binary formats for file I/O or network communication.
| Directive | Description |
|---|---|
@ | Moves to absolute position in the output string. |
A | ASCII string (space padded, count is width). |
a | ASCII string (null padded, count is width). |
B | Bit string (bits in descending order inside each byte). |
b | Bit string (bits in ascending order inside each byte). |
C | Unsigned 8-bit integer (unsigned char). |
c | Signed 8-bit integer (char). |
D, d | Double-precision float, native format. |
E | Double-precision float, little-endian byte order. |
e | Single-precision float, little-endian byte order. |
F, f | Single-precision float, native format. |
G | Double-precision float, network (big-endian) byte order. |
g | Single-precision float, network (big-endian) byte order. |
H | Hex string (high nibble first). |
h | Hex string (low nibble first). |
I | Unsigned integer (usually 32-bit). Suffix _ for platform native, < for little-endian, > for big-endian. |
i | Signed integer (usually 32-bit). Suffix _ for platform native, < for little-endian, > for big-endian. |
L | Unsigned long (usually 32-bit or 64-bit based on platform/suffix). Suffix _ for platform native, < for little-endian, > for big-endian. |
l | Signed long (usually 32-bit or 64-bit based on platform/suffix). Suffix _ for platform native, < for little-endian, > for big-endian. |
M | Quoted-printable encoding (RFC 2045). |
m | Base64 encoded string. |
N | Unsigned 32-bit integer, network (big-endian) byte order. |
n | Unsigned 16-bit integer, network (big-endian) byte order. |
P | Pointer to a structure (fixed-length string of specified length). |
p | Pointer to a null-terminated string. |
Q | Unsigned 64-bit integer. Suffix < for little-endian, > for big-endian. |
q | Signed 64-bit integer. Suffix < for little-endian, > for big-endian. |
S | Unsigned short (usually 16-bit). Suffix _ for platform native, < for little-endian, > for big-endian. |
s | Signed short (usually 16-bit). Suffix _ for platform native, < for little-endian, > for big-endian. |
U | UTF-8 character(s). |
u | UU-encoded string. |
V | Unsigned 32-bit integer, little-endian byte order. |
v | Unsigned 16-bit integer, little-endian byte order. |
w | BER-compressed integer. |
X | Back up a byte. |
x | Null byte. |
Z | ASCII string (null terminated). If count is *, consumes all remaining items. |
Example of pack:
Section titled “Example of pack:”This example demonstrates packing various data types into binary strings:
#!/usr/bin/ruby
letters = ["a", "b", "c"]numbers = [65, 66, 67] # ASCII for A, B, C
packed_A = letters.pack("A3A3A3")puts "Packed with A3A3A3: #{packed_A.inspect}" # => "\"a b c \""
packed_a = letters.pack("a3a3a3")puts "Packed with a3a3a3: #{packed_a.inspect}" # => "\"a\x00\x00b\x00\x00c\x00\x00\""
packed_chars = numbers.pack("ccc")puts "Packed with ccc: #{packed_chars.inspect}" # => "\"ABC\""puts "Packed string itself: #{packed_chars}" # => "ABC"
packed_network_short = [256*1 + 2].pack("n") # 258 in big-endian shortputs "Packed 258 as network short: #{packed_network_short.inspect}" # => "\"\x01\x02\""The unpack method (String#unpack) is the counterpart to Array#pack, used to convert binary strings back into arrays of data.
Practical Applications:
Arrays are fundamental in Ruby. They are used to store lists of items, such as user records from a database, lines from a file, or a sequence of steps in an algorithm. Their rich API makes them suitable for a wide range of data manipulation tasks, from simple queues and stacks to complex data processing pipelines.