1. 什么是数组?

数组是一个有序的、可变的对象集合,用 [] 定义。数组中的元素通过索引(从 0 开始)访问。

基本定义

fruits = ["苹果", "香蕉", "橙子"]
numbers = [1, 2, 3, 4]
mixed = ["你好", 42, true]
puts fruits  # ["苹果", "香蕉", "橙子"]

其他定义方式

# 空数组
empty = []

# 多行定义
tasks = [
  "写代码",
  "开会",
  "休息"
]

# %w 快速创建字符串数组
words = %w(你好 世界 Ruby)
puts words  # ["你好", "世界", "Ruby"]

2. 访问数组元素

通过索引

fruits = ["苹果", "香蕉", "橙子"]
puts fruits[0]    # 苹果
puts fruits[-1]   # 橙子(负索引从末尾开始)
puts fruits[1..2] # ["香蕉", "橙子"](范围切片)

注意

  • 超出索引返回 nil
  puts fruits[10]  # nil

3. 修改数组

添加元素

  • <<push:末尾添加
  fruits = ["苹果"]
  fruits << "香蕉"
  fruits.push("橙子")
  puts fruits  # ["苹果", "香蕉", "橙子"]
  • unshift:开头添加
  fruits.unshift("葡萄")
  puts fruits  # ["葡萄", "苹果", "香蕉", "橙子"]

删除元素

  • pop:删除并返回末尾元素
  fruits = ["苹果", "香蕉", "橙子"]
  last = fruits.pop
  puts last    # 橙子
  puts fruits  # ["苹果", "香蕉"]
  • shift:删除并返回开头元素
  first = fruits.shift
  puts first   # 苹果
  puts fruits  # ["香蕉"]
  • delete:删除指定元素
  fruits.delete("香蕉")
  puts fruits  # []
  • delete_at:删除指定索引
  fruits = ["苹果", "香蕉", "橙子"]
  fruits.delete_at(1)
  puts fruits  # ["苹果", "橙子"]

替换元素

fruits = ["苹果", "香蕉"]
fruits[1] = "橙子"
puts fruits  # ["苹果", "橙子"]

4. 常用方法

长度与状态

tasks = ["写代码", "开会"]
puts tasks.length   # 2
puts tasks.size     # 2(同 length)
puts tasks.empty?   # false
puts tasks.include?("开会")  # true

遍历

  • each
  fruits = ["苹果", "香蕉", "橙子"]
  fruits.each do |fruit|
    puts "我喜欢 #{fruit}"
  end

输出:

  我喜欢 苹果
  我喜欢 香蕉
  我喜欢 橙子
  • each_with_index
  fruits.each_with_index do |fruit, index|
    puts "#{index + 1}. #{fruit}"
  end

输出:

  1. 苹果
  2. 香蕉
  3. 橙子

转换

  • map:生成新数组
  numbers = [1, 2, 3]
  doubled = numbers.map { |n| n * 2 }
  puts doubled  # [2, 4, 6]
  • join:合并为字符串
  fruits = ["苹果", "香蕉"]
  puts fruits.join(" 和 ")  # 苹果 和 香蕉

过滤

  • select:筛选符合条件的元素
  numbers = [1, 2, 3, 4]
  even = numbers.select { |n| n % 2 == 0 }
  puts even  # [2, 4]
  • reject:排除符合条件的元素
  odd = numbers.reject { |n| n % 2 == 0 }
  puts odd  # [1, 3]

排序

numbers = [3, 1, 4, 2]
puts numbers.sort  # [1, 2, 3, 4]

words = ["橙子", "苹果", "香蕉"]
puts words.sort    # ["橙子", "苹果", "香蕉"](按 Unicode)

5. 多维数组

定义

matrix = [
  [1, 2, 3],
  [4, 5, 6]
]
puts matrix[0][1]  # 2

遍历

matrix.each do |row|
  row.each do |num|
    print "#{num} "
  end
  puts
end

输出:

1 2 3 
4 5 6 

6. 中文支持示例

处理中文数组

任务 = ["写代码", "开会", "休息"]
任务.each do |task|
  puts "今天要 #{task}"
end

输出:

今天要 写代码
今天要 开会
今天要 休息

实践案例

class TaskList
  def initialize
    @tasks = []
  end

  def add(task)
    @tasks << task
  end

  def show
    @tasks.each_with_index { |task, i| puts "#{i + 1}. #{task}" }
  end
end

list = TaskList.new
list.add("买菜")
list.add("做饭")
list.show

输出:

1. 买菜
2. 做饭

7. 数组的不可变性与修改

普通方法

大多数方法返回新数组,不修改原数组:

numbers = [1, 2, 3]
sorted = numbers.sort
puts numbers  # [1, 2, 3]
puts sorted   # [1, 2, 3]

破坏性方法(带 !

修改原数组:

numbers = [3, 1, 2]
numbers.sort!
puts numbers  # [1, 2, 3]

fruits = ["苹果", "香蕉"]
fruits.reverse!
puts fruits   # ["香蕉", "苹果"]

8. 实践案例

案例 1:成绩统计

scores = [85, 92, 78, 95]
average = scores.sum / scores.length.to_f
puts "平均分:#{average}"  # 平均分:87.5

案例 2:购物清单

cart = ["手机", "耳机"]
cart << "充电器"
puts "购物清单:#{cart.join(', ')}"  # 购物清单:手机, 耳机, 充电器

案例 3:过滤任务

tasks = ["写代码", "开会", "休息", "测试"]
urgent = tasks.select { |task| task.length > 2 }
puts urgent  # ["写代码", "休息"]

9. 注意事项

  • 索引:越界访问返回 nil,不会抛出异常。
  • 性能:频繁添加元素时,<<+= 更高效(后者创建新数组)。
  • 类型混合:数组可以包含任意类型,但操作时需注意类型一致性。

下一步

  • 练习:告诉我你想用数组做什么(遍历、排序等),我可以设计一个例子。
  • 问题解答:对数组用法有疑问吗?直接问我!
  • 深入学习:想了解数组与哈希的结合或性能优化吗?我可以继续讲解。

你现在想做什么?写代码、问问题,还是其他?