Ruby 数组
Ruby 数组:有序集合
Section titled “Ruby 数组:有序集合”Ruby 数组是功能强大、有序的集合,可以包含任何类型的对象,包括数字、字符串、hash,甚至其他数组。数组中的每个元素都通过基于整数的索引来访问。
数组索引从 0 开始,类似于 C 或 Java 等语言。负数索引从数组末尾开始计数:-1 指最后一个元素,-2 指倒数第二个,依此类推。Ruby 数组是动态的,这意味着当你添加或删除元素时,它们会自动增长或缩小。
创建数组最常见的方式是使用数组字面量语法 []:
# 一个空数组empty_array = []
# 一个数字数组numbers = [1, 2, 3, 4, 5]
# 一个混合类型数组mixed_array = [1, "hello", :symbol, ["nested", "array"]]你也可以使用 Array.new 类方法:
#!/usr/bin/ruby
# 创建一个空数组names = Array.new
# 创建一个具有预定义大小(20 个元素,全部为 nil)的数组names_with_size = Array.new(20)
# 返回数组的大小(或长度)puts names_with_size.size # 输出: 20puts names_with_size.length # 输出: 20你可以用一个默认值初始化数组的所有元素:
#!/usr/bin/ruby
default_values_array = Array.new(4, "default")puts default_values_array.inspect # 输出: ["default", "default", "default", "default"]使用可变对象进行初始化时要小心。所有元素将引用同一个对象:
#!/usr/bin/ruby
# 如果你想要不同的可变对象,这种方式是不正确的array_of_hashes = Array.new(3, {})array_of_hashes[0][:name] = "Alice"puts array_of_hashes.inspect # 输出: [{:name=>"Alice"}, {:name=>"Alice"}, {:name=>"Alice"}]
# 使用块来获取不同的可变对象的正确方式distinct_hashes_array = Array.new(3) { {} }distinct_hashes_array[0][:name] = "Alice"puts distinct_hashes_array.inspect # 输出: [{:name=>"Alice"}, {}, {}]你也可以使用带块的 new 方法来动态填充每个元素:
#!/usr/bin/ruby
squares = Array.new(5) { |index| index * index }puts squares.inspect # 输出: [0, 1, 4, 9, 16]创建数组的其他方式包括 Array.[] 或 Kernel#Array 方法:
nums1 = Array.[](1, 2, 3, 4, 5)nums2 = Array[1, 2, 3, 4, 5]
# 使用 Kernel#Array 和 rangedigits = Array(0..9)puts digits.inspect # 输出: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]数组内置方法:
Section titled “数组内置方法:”数组自带一套丰富的内置方法,用于操作、迭代和查询。下面是一个例子:
#!/usr/bin/ruby
digits = Array(0..9) # 创建 [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}" # 输出: Element at index 6: 6
first_three = digits.first(3)puts "First three elements: #{first_three.inspect}" # 输出: First three elements: [0, 1, 2]
digits.push(10) # 在末尾添加 10puts "After push(10): #{digits.inspect}" # 输出: After push(10): [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
last_element = digits.pop # 删除并返回最后一个元素puts "Popped element: #{last_element}" # 输出: Popped element: 10puts "After pop: #{digits.inspect}" # 输出: After pop: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]下表是常用的公共数组方法(假设 array 是一个 Array 对象)。有关完整列表,请务必查阅官方 Ruby 文档。
| 序号 | 方法及其描述 |
|---|---|
| 1 | array & other_array (交集)返回一个包含两个数组共有元素的、无重复的新数组。 array.intersection(other_array) 是其别名。 |
| 2 | array * int (重复) 或 array * str (连接)如果 int 是一个整数,返回一个由 array 重复 int 次连接而成的新数组。如果 str 是一个字符串,则等同于 self.join(str)。 |
| 3 | array + other_array (连接)通过连接两个数组返回一个新数组。不修改原始数组。 |
| 4 | array - other_array (差集)返回一个新数组,它是原始 array 的副本,移除其中在 other_array 中出现的任何项。array.difference(other_array) 是其别名。 |
| 5 | array <=> other_array (比较)逐元素比较两个数组。如果 array 分别小于、等于或大于 other_array,则返回 -1、0 或 1。 |
| 6 | array | other_array (并集)通过将 array 与 other_array 合并,并移除重复项,返回一个新数组。array.union(other_array) 是其别名。 |
| 7 | array << obj (追加/推入)将给定对象 obj 推入 array 的末尾。就地修改 array 并返回 array 本身,允许链式追加。 |
| 8 | array == other_array (相等性)如果两个数组包含相同数量的元素且每个对应的元素都相等(使用 == 检查),则返回 true。 |
| 9 | array[index]、array[start, length]、array[range]、array.slice(...) (元素访问/切片)返回一个元素或一个子数组。负数索引从末尾计数。如果索引超出范围,返回 nil。 |
| 10 | array[index] = obj、array[start, length] = new_subarray、array[range] = new_subarray (元素赋值)为元素赋值新值或替换子数组。如果索引超出边界,数组会自动增长。 |
| 11 | array.at(index)返回位于 index 的元素。负数索引从末尾计数。如果索引超出范围,返回 nil。 |
| 12 | array.clear移除 array 中的所有元素,使其变空。就地修改 array。 |
| 13 | array.collect { |item| block } 或 array.map { |item| block } (转换)对 array 的每个元素调用一次 block。创建一个包含块返回值的新数组。不修改原始数组。 |
| 14 | array.collect! { |item| block } 或 array.map! { |item| block } (就地转换)对 array 的每个元素调用一次 block,将元素替换为块返回的值。就地修改 array。 |
| 15 | array.compact返回一个移除了所有 nil 元素的新数组。不修改原始数组。 |
| 16 | array.compact!就地从 array 中移除 nil 元素。如果未做任何更改,返回 nil。 |
| 17 | array.concat(other_array, ...)将 other_array(s) 的元素追加到 array。就地修改 array。 |
| 18 | array.delete(obj) { |obj| block }从 array 中删除所有等于 obj 的项。如果提供了可选的 block,则在未找到 obj 时执行。就地修改 array。 |
| 19 | array.delete_at(index)删除指定 index 处的元素,并返回该元素;如果索引超出范围,则返回 nil。就地修改 array。 |
| 20 | array.delete_if { |item| block } 或 array.reject! { |item| block }删除 array 中 block 求值为 true 的每个元素。就地修改 array。 |
| 21 | array.each { |item| block } (迭代)对 array 中的每个元素调用一次 block,将该元素作为参数传递。这是迭代数组最常用的方法之一。 |
| 22 | array.each_index { |index| block }与 Array#each 相同,但传递元素的 index 而非元素本身。 |
| 23 | array.empty?如果 array 不包含任何元素,则返回 true,否则返回 false。 |
| 24 | array.fetch(index)、array.fetch(index, default)、array.fetch(index) { |index| block }返回位于 index 的元素。如果 index 超出范围,则根据使用的形式,抛出 IndexError 异常、返回 default 或执行 block。 |
| 25 | array.fill(obj)、array.fill(obj, start [, length])、array.fill(obj, range) 或带块的形式将 array 中选定的元素设置为 obj 或设置为 block 的结果。就地修改 array。 |
| 26 | array.first 或 array.first(n)返回 array 的第一个元素,或前 n 个元素。如果 array 为空,第一种形式返回 nil,第二种形式返回一个空数组。 |
| 27 | array.flatten返回一个将 array 展平为一维的新数组(递归)。 |
| 28 | array.flatten!就地展平 array。如果没有进行任何修改(即 array 不包含子数组),则返回 nil。 |
| 29 | array.include?(obj)如果 obj 存在于 array 中(使用 == 检查),则返回 true,否则返回 false。 |
| 30 | array.index(obj) 或 array.find_index(obj)返回 array 中第一个等于 obj 的元素的索引。如果未找到匹配项,则返回 nil。 |
| 31 | array.insert(index, obj...)将给定的 obj(s) 插入到给定 index 处的元素之前。就地修改 array。 |
| 32 | array.join(separator = $,)返回一个字符串,该字符串通过将 array 的每个元素转换为字符串,并用 separator 分隔而成(如果 $, 为 nil,默认分隔符为空字符串)。 |
| 33 | array.last 或 array.last(n)返回 array 的最后一个或最后 n 个元素。如果 array 为空,第一种形式返回 nil。 |
| 34 | array.length 或 array.size返回 array 中的元素数量。 |
| 35 | array.pop(n=1)从 array 中移除最后的 n 个元素并返回它们(如果 n=1 则返回单个元素)。如果 array 为空,返回 nil 或一个空数组。就地修改 array。 |
| 36 | array.push(obj, ...) 或 array.append(obj, ...)将给定的 obj(s) 追加到 array 的末尾。就地修改 array 并返回 array 本身。 |
| 37 | array.reject { |item| block }返回一个新数组,包含 array 中 block 求值为 false 的项。不修改原始数组。 |
| 38 | array.reverse返回一个包含 array 元素逆序的新数组。 |
| 39 | array.reverse!就地反转 array。 |
| 40 | array.select { |item| block } 或 array.filter { |item| block } (过滤)对每个元素调用 block。返回一个新数组,包含 block 返回真值的那些元素。 |
| 41 | array.select! { |item| block } 或 array.filter! { |item| block } (就地过滤)删除 array 中 block 求值为 false 的元素。就地修改 array。 |
| 42 | array.shift(n=1)从 array 中移除前 n 个元素并返回它们。就地修改 array。 |
| 43 | array.sort 或 array.sort { |a, b| block }返回一个通过排序 array 创建的新数组。如果提供了 block,它应该实现 a 和 b 之间的比较(返回 -1、0 或 1)。 |
| 44 | array.sort! 或 array.sort! { |a, b| block }就地排序 array。 |
| 45 | array.uniq通过从 array 中移除重复值返回一个新数组。 |
| 46 | array.uniq!就地从 array 中移除重复元素。如果未做任何更改,则返回 nil。 |
| 47 | array.unshift(obj, ...) 或 array.prepend(obj, ...)将 obj(s) 前置到 array 的开头,并将其他元素向后移动。就地修改 array。 |
| 48 | array.values_at(selector, ...)返回一个数组,其中包含 array 中对应于给定 selector(s)(整数索引或 range)的元素。 |
| 49 | array.zip(other_array1, ...)将参数转换为数组,然后将 array 的元素与每个参数中对应的元素合并。它会生成一个数组的数组。 |
Array#pack 方法和指令:
Section titled “Array#pack 方法和指令:”pack 方法是一个强大的工具,用于根据模板字符串将数组转换为二进制字符串序列。这通常用于创建特定二进制格式的数据,以便进行 File I/O 或网络通信。
| 指令 | 描述 |
|---|---|
@ | 移动到输出字符串中的绝对位置。 |
A | ASCII 字符串(用空格填充,计数是宽度)。 |
a | ASCII 字符串(用 null 填充,计数是宽度)。 |
B | 位字符串(每个字节内位以降序排列)。 |
b | 位字符串(每个字节内位以升序排列)。 |
C | 无符号 8 位整数(unsigned char)。 |
c | 有符号 8 位整数(char)。 |
D, d | 双精度浮点数,原生格式。 |
E | 双精度浮点数,小端字节序。 |
e | 单精度浮点数,小端字节序。 |
F, f | 单精度浮点数,原生格式。 |
G | 双精度浮点数,网络(大端)字节序。 |
g | 单精度浮点数,网络(大端)字节序。 |
H | 十六进制字符串(高半字节在前)。 |
h | 十六进制字符串(低半字节在前)。 |
I | 无符号整数(通常是 32 位)。后缀 _ 表示平台原生,< 表示小端,> 表示大端。 |
i | 有符号整数(通常是 32 位)。后缀 _ 表示平台原生,< 表示小端,> 表示大端。 |
L | 无符号长整数(通常基于平台/后缀是 32 位或 64 位)。后缀 _ 表示平台原生,< 表示小端,> 表示大端。 |
l | 有符号长整数(通常基于平台/后缀是 32 位或 64 位)。后缀 _ 表示平台原生,< 表示小端,> 表示大端。 |
M | Quoted-printable 编码 (RFC 2045)。 |
m | Base64 编码字符串。 |
N | 无符号 32 位整数,网络(大端)字节序。 |
n | 无符号 16 位整数,网络(大端)字节序。 |
P | 指向结构的指针(指定长度的固定长度字符串)。 |
p | 指向 null 终止字符串的指针。 |
Q | 无符号 64 位整数。后缀 < 表示小端,> 表示大端。 |
q | 有符号 64 位整数。后缀 < 表示小端,> 表示大端。 |
S | 无符号短整数(通常是 16 位)。后缀 _ 表示平台原生,< 表示小端,> 表示大端。 |
s | 有符号短整数(通常是 16 位)。后缀 _ 表示平台原生,< 表示小端,> 表示大端。 |
U | UTF-8 字符。 |
u | UU 编码字符串。 |
V | 无符号 32 位整数,小端字节序。 |
v | 无符号 16 位整数,小端字节序。 |
w | BER 压缩整数。 |
X | 回退一个字节。 |
x | null 字节。 |
Z | ASCII 字符串(null 终止)。如果计数是 *,则消耗所有剩余项。 |
pack 示例:
Section titled “pack 示例:”此示例演示了将各种数据类型打包成二进制字符串:
#!/usr/bin/ruby
letters = ["a", "b", "c"]numbers = [65, 66, 67] # A, B, C 的 ASCII 值
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 的大端短整数表示puts "Packed 258 as network short: #{packed_network_short.inspect}" # => "\"\x01\x02\""unpack 方法(String#unpack)是 Array#pack 的对应方法,用于将二进制字符串转换回数据数组。
实际应用:
数组在 Ruby 中是基础概念。它们用于存储项目列表,例如来自数据库的用户记录、文件中的行或算法中的一系列步骤。其丰富的 API 使它们适用于各种数据操作任务,从简单的队列和栈到复杂的数据处理管道。