Ruby标准库Skill ruby-standard-library

Ruby标准库是Ruby编程语言的核心组成部分,提供了丰富的内置类和方法,用于高效处理常见编程任务,如集合迭代、文件操作、字符串处理、正则表达式匹配、时间日期管理等。它包含了Enumerable模块、Array、Hash、String等核心类,以及File I/O、Time/Date等模块,使Ruby开发更加优雅和便捷。关键词:Ruby标准库,Enumerable,文件操作,正则表达式,核心类,Ruby编程。

后端开发 0 次安装 0 次浏览 更新于 3/25/2026

name: ruby-standard-library user-invocable: false description: 当使用Ruby标准库时使用,包括Enumerable、文件I/O、时间/日期、正则表达式和核心类。 allowed-tools:

  • Bash
  • Read
  • Write
  • Edit

Ruby标准库

掌握Ruby丰富的标准库。Ruby附带强大的内置类和方法,优雅地处理常见编程任务。

Enumerable

Enumerable模块为集合提供迭代方法。

常见的Enumerable方法

numbers = [1, 2, 3, 4, 5]

# map/collect - 转换元素
numbers.map { |n| n * 2 }  # [2, 4, 6, 8, 10]
numbers.map(&:to_s)        # ["1", "2", "3", "4", "5"]

# select/filter - 保留匹配条件的元素
numbers.select { |n| n.even? }  # [2, 4]
numbers.filter(&:odd?)          # [1, 3, 5]

# reject - 移除匹配条件的元素
numbers.reject { |n| n.even? }  # [1, 3, 5]

# find/detect - 第一个匹配条件的元素
numbers.find { |n| n > 3 }  # 4

# find_all - 所有匹配条件的元素(select的别名)
numbers.find_all { |n| n > 2 }  # [3, 4, 5]

# reduce/inject - 累积值
numbers.reduce(0) { |sum, n| sum + n }  # 15
numbers.reduce(:+)  # 15
numbers.reduce(:*)  # 120

# each - 遍历元素
numbers.each { |n| puts n }

# each_with_index - 带索引遍历
numbers.each_with_index { |n, i| puts "#{i}: #{n}" }

# each_with_object - 带可变对象遍历
numbers.each_with_object({}) { |n, hash| hash[n] = n * 2 }

# any? - 如果有任何元素匹配则为真
numbers.any? { |n| n > 4 }  # true
numbers.any?(&:even?)       # true

# all? - 如果所有元素匹配则为真
numbers.all? { |n| n > 0 }  # true
numbers.all?(&:even?)       # false

# none? - 如果没有元素匹配则为真
numbers.none? { |n| n < 0 }  # true

# one? - 如果恰好一个元素匹配则为真
numbers.one? { |n| n == 3 }  # true

# partition - 分割为两个数组[匹配, 不匹配]
evens, odds = numbers.partition(&:even?)

# group_by - 按键分组元素
numbers.group_by { |n| n % 2 == 0 ? :even : :odd }
# => {:odd=>[1, 3, 5], :even=>[2, 4]}

# chunk - 分组连续元素
[1, 2, 2, 3, 3, 3, 4].chunk(&:itself).to_a
# => [[1, [1]], [2, [2, 2]], [3, [3, 3, 3]], [4, [4]]]

# take - 前n个元素
numbers.take(3)  # [1, 2, 3]

# drop - 跳过前n个元素
numbers.drop(3)  # [4, 5]

# take_while - 元素直到条件失败
numbers.take_while { |n| n < 4 }  # [1, 2, 3]

# drop_while - 跳过元素直到条件失败
numbers.drop_while { |n| n < 4 }  # [4, 5]

# zip - 组合数组
[1, 2, 3].zip(['a', 'b', 'c'])  # [[1, "a"], [2, "b"], [3, "c"]]

# min, max
numbers.min  # 1
numbers.max  # 5
numbers.minmax  # [1, 5]

# sort
[3, 1, 4, 1, 5].sort  # [1, 1, 3, 4, 5]
['猫', '狗', '鸟'].sort_by(&:length)

# uniq - 移除重复元素
[1, 2, 2, 3, 3, 3].uniq  # [1, 2, 3]

# compact - 移除nil值
[1, nil, 2, nil, 3].compact  # [1, 2, 3]

# flat_map - 映射并展平
[[1, 2], [3, 4]].flat_map { |arr| arr.map { |n| n * 2 } }  # [2, 4, 6, 8]

# tally - 计数出现次数
['a', 'b', 'a', 'c', 'b', 'a'].tally  # {"a"=>3, "b"=>2, "c"=>1}

数组

# 创建
arr = [1, 2, 3]
arr = Array.new(3, 0)  # [0, 0, 0]
arr = Array.new(3) { |i| i * 2 }  # [0, 2, 4]

# 访问
arr[0]        # 第一个元素
arr[-1]       # 最后一个元素
arr[1..3]     # 范围
arr.first     # 1
arr.last      # 3
arr.at(1)     # 2

# 修改
arr << 4              # 追加
arr.push(5)           # 追加
arr.unshift(0)        # 前置
arr.pop               # 移除并返回最后一个
arr.shift             # 移除并返回第一个
arr.delete_at(1)      # 删除索引处
arr.delete(3)         # 删除值
arr.insert(1, 'a')    # 在索引处插入

# 组合
[1, 2] + [3, 4]       # [1, 2, 3, 4]
[1, 2] * 2            # [1, 2, 1, 2]
[1, 2, 3] - [2]       # [1, 3]
[1, 2] & [2, 3]       # [2](交集)
[1, 2] | [2, 3]       # [1, 2, 3](并集)

# 查询
arr.include?(2)       # true
arr.empty?            # false
arr.length            # 3
arr.count             # 3
arr.count(2)          # 计数出现次数

# 转换
arr.reverse           # [3, 2, 1]
arr.flatten           # 展平嵌套数组
arr.compact           # 移除nil
arr.uniq              # 移除重复
arr.join(', ')        # 转换为字符串
arr.sample            # 随机元素
arr.shuffle           # 随机顺序

哈希

# 创建
hash = { name: '爱丽丝', age: 30 }
hash = Hash.new(0)  # 默认值0
hash = Hash.new { |h, k| h[k] = [] }  # 默认块

# 访问
hash[:name]           # '爱丽丝'
hash.fetch(:age)      # 30
hash.fetch(:email, '不适用')  # 带默认值
hash.dig(:person, :name)   # 安全嵌套访问

# 修改
hash[:email] = '爱丽丝@example.com'
hash.delete(:age)
hash.merge!(other_hash)
hash.transform_keys(&:to_s)
hash.transform_values { |v| v.to_s }

# 迭代
hash.each { |key, value| puts "#{key}: #{value}" }
hash.each_key { |key| puts key }
hash.each_value { |value| puts value }

# 查询
hash.key?(:name)      # true
hash.value?('爱丽丝')  # true
hash.empty?           # false
hash.size             # 2

# 转换
hash.keys             # [:name, :age]
hash.values           # ['爱丽丝', 30]
hash.invert           # 交换键和值
hash.select { |k, v| v.is_a?(String) }
hash.reject { |k, v| v.nil? }
hash.compact          # 移除nil值
hash.slice(:name, :age)  # 提取子集

字符串

str = "你好,世界!"

# 大小写
str.upcase            # "你好,世界!"(注:中文无大小写变化,保持原样)
str.downcase          # "你好,世界!"
str.capitalize        # "你好,世界!"
str.swapcase          # "你好,世界!"
str.titleize          # 需要ActiveSupport

# 修剪
"  你好  ".strip    # "你好"
"  你好  ".lstrip   # "你好  "
"  你好  ".rstrip   # "  你好"

# 搜索
str.include?("世界")    # true
str.start_with?("你好") # true
str.end_with?("!")       # true
str.index("世界")       # 3
str.rindex("好")          # 1

# 分割和连接
"a,b,c".split(",")       # ["a", "b", "c"]
["a", "b", "c"].join("-")  # "a-b-c"

# 替换
str.sub("世界", "Ruby")    # 替换第一个
str.gsub("好", "0")          # 替换所有
str.delete("好")             # 移除字符
str.tr("aeiou", "12345")    # 翻译字符(示例保持)

# 子字符串
str[0]                # "你"
str[0..2]             # "你好,"
str[3..]              # "世界!"
str.slice(0, 2)       # "你好"

# 查询
str.empty?            # false
str.length            # 5
str.size              # 5
str.count("好")        # 1

# 转换
"123".to_i            # 123
"3.14".to_f           # 3.14
:symbol.to_s          # "symbol"

# 编码
str.encoding          # #<Encoding:UTF-8>
str.force_encoding("ASCII")
str.encode("ISO-8859-1")

# 多行
text = <<~HEREDOC
  这是一个
  多行字符串
  缩进已移除
HEREDOC

正则表达式

# 创建
regex = /pattern/
regex = Regexp.new("pattern")

# 匹配
"hello" =~ /ll/               # 2(索引)
"hello" !~ /zz/               # true
"hello".match(/l+/)           # #<MatchData "ll">
"hello".match?(/l+/)          # true(更快,无MatchData)

# 匹配数据
match = "hello123".match(/(\w+)(\d+)/)
match[0]                      # "hello123"(完全匹配)
match[1]                      # "hello"(第一组)
match[2]                      # "123"(第二组)

# 命名捕获
match = "hello123".match(/(?<word>\w+)(?<num>\d+)/)
match[:word]                  # "hello"
match[:num]                   # "123"

# 字符串方法带正则表达式
"hello world".scan(/\w+/)     # ["hello", "world"]
"a1b2c3".scan(/\d/)           # ["1", "2", "3"]

"hello".sub(/l/, 'L')         # "heLlo"
"hello".gsub(/l/, 'L')        # "heLLo"

"a:b:c".split(/:/)            # ["a", "b", "c"]

# 标志
/pattern/i                    # 不区分大小写
/pattern/m                    # 多行
/pattern/x                    # 扩展(忽略空白)

# 常见模式
/\d+/                         # 一个或多个数字
/\w+/                         # 一个或多个单词字符
/\s+/                         # 一个或多个空白字符
/^start/                      # 字符串开始
/end$/                        # 字符串结束
/[aeiou]/                     # 字符类
/[^aeiou]/                    # 否定类
/(cat|dog)/                   # 交替

文件I/O

# 读取
content = File.read("文件.txt")
lines = File.readlines("文件.txt")

File.open("文件.txt", "r") do |file|
  file.each_line do |line|
    puts line
  end
end

# 写入
File.write("文件.txt", "内容")

File.open("文件.txt", "w") do |file|
  file.puts "第一行"
  file.puts "第二行"
end

# 追加
File.open("文件.txt", "a") do |file|
  file.puts "追加行"
end

# 文件模式
# "r"  - 只读
# "w"  - 写入(截断)
# "a"  - 追加
# "r+" - 读取和写入
# "w+" - 读取和写入(截断)
# "a+" - 读取和追加

# 文件操作
File.exist?("文件.txt")       # true/false
File.file?("文件.txt")        # 是否是文件?
File.directory?("目录")        # 是否是目录?
File.size("文件.txt")         # 大小(字节)
File.mtime("文件.txt")        # 修改时间
File.basename("/路径/到/文件.txt")  # "文件.txt"
File.dirname("/路径/到/文件.txt")   # "/路径/到"
File.extname("文件.txt")      # ".txt"
File.join("路径", "到", "文件.txt")  # "路径/到/文件.txt"

# 目录操作
Dir.entries(".")              # 列出目录
Dir.glob("*.rb")              # 模式匹配
Dir.glob("**/*.rb")           # 递归

Dir.mkdir("新目录")
Dir.rmdir("旧目录")
Dir.pwd                       # 当前目录
Dir.chdir("/路径")            # 更改目录

FileUtils.mkdir_p("a/b/c")    # 创建嵌套目录
FileUtils.rm_rf("目录")        # 递归移除
FileUtils.cp("源", "目标")   # 复制文件
FileUtils.mv("源", "目标")   # 移动文件

时间和日期

require 'time'
require 'date'

# 时间
now = Time.now
utc = Time.now.utc
local = Time.now.localtime

# 组件
now.year              # 2024
now.month             # 11
now.day               # 25
now.hour              # 14
now.min               # 30
now.sec               # 45
now.wday              # 星期几(0=星期日)

# 创建
Time.new(2024, 11, 25, 14, 30, 45)
Time.parse("2024-11-25 14:30:45")
Time.at(1700000000)   # 从Unix时间戳

# 格式化
now.strftime("%Y-%m-%d %H:%M:%S")
now.strftime("%B %d, %Y")          # 十一月 25, 2024
now.iso8601                        # ISO 8601格式

# 算术
now + 3600            # 添加1小时(秒)
now - 86400           # 减去1天
time2 - time1         # 差异(秒)

# 日期
date = Date.today
date = Date.new(2024, 11, 25)
date = Date.parse("2024-11-25")

date.year             # 2024
date.month            # 11
date.day              # 25
date.wday             # 1(星期一)

date + 7              # 添加7天
date - 7              # 减去7天
date.next_day         # 明天
date.prev_day         # 昨天
date.next_month       # 下个月
date.prev_year        # 去年

# DateTime(结合日期和时间)
dt = DateTime.now
dt = DateTime.parse("2024-11-25T14:30:45")

范围

# 包含
(1..5).to_a           # [1, 2, 3, 4, 5]

# 排除
(1...5).to_a          # [1, 2, 3, 4]

# 方法
(1..10).include?(5)   # true
(1..10).cover?(5)     # true(更快)
(1..10).member?(5)    # true

(1..5).each { |n| puts n }
(1..5).map { |n| n * 2 }

# 字符串范围
('a'..'e').to_a       # ["a", "b", "c", "d", "e"]

# case语句
case age
when 0..12
  "儿童"
when 13..19
  "青少年"
else
  "成人"
end

集合

require 'set'

# 创建
set = Set.new([1, 2, 3])
set = Set[1, 2, 3]

# 操作
set.add(4)
set << 5
set.delete(3)

# 集合操作
set1 | set2           # 并集
set1 & set2           # 交集
set1 - set2           # 差集
set1 ^ set2           # 对称差集

# 查询
set.include?(2)       # true
set.empty?            # false
set.size              # 3

# 子集/超集
set1.subset?(set2)
set1.superset?(set2)

最佳实践

  1. 使用Enumerable方法 而不是手动循环
  2. 链式方法 以提高可读性:array.select(&:even?).map(&:to_s)
  3. 使用符号到Proc&:method_name)当可能时
  4. 优先使用带块的File.open 以自动关闭文件
  5. 对哈希使用fetch 当你想处理缺失键时
  6. 利用惰性枚举 对于大型集合
  7. 使用Pathname 对于复杂路径操作

反模式

不要使用for循环 - 使用Enumerable方法 ❌ 不要忘记关闭文件 - 使用带块的File.open ❌ 不要使用each进行转换 - 使用map不要使用each进行过滤 - 使用selectreject不要在迭代时修改数组 - 使用返回新数组的方法

相关技能

  • ruby-oop - 用于理解核心类
  • ruby-blocks-procs-lambdas - 用于使用Enumerable
  • ruby-metaprogramming - 用于高级库用法