Ruby 迭代器
Ruby 迭代器(Iterators):each、map 等
Section titled “Ruby 迭代器(Iterators):each、map 等”迭代器(Iterators)是反复调用代码块来处理集合(如 Array 或 Hash)中每个元素的方法。它们是 Ruby 处理集合时表达力强且简洁风格的基石。
Ruby 的 Enumerable 模块混入(mixed into)了 Array 和 Hash 等类中,提供了丰富的迭代器方法。我们将重点介绍 each 和 map(也称为 collect),并简要提及其他一些方法。
each 迭代器:
Section titled “each 迭代器:”each 迭代器是最基础的迭代器之一。它对集合中的每个元素执行给定的块一次,并将元素作为参数传递给块。each 总是返回调用它的原始集合。
collection.each do |variable| # code to execute for each elementend
# Or for single-line blocks:collection.each { |variable| # code }Array 示例:
Section titled “Array 示例:”#!/usr/bin/env ruby
numbers = [1, 2, 3, 4, 5]
puts "Iterating through numbers:"numbers.each do |number| puts "Current number: #{number}"end
# The return value of each is the original arrayreturned_value = numbers.each { |n| n * 2 } # The block's result is discarded by eachputs "Returned value from 'each': #{returned_value.inspect}" #=> [1, 2, 3, 4, 5]这将产生以下结果:
Iterating through numbers:Current number: 1Current number: 2Current number: 3Current number: 4Current number: 5Returned value from 'each': [1, 2, 3, 4, 5]Hash 示例:
Section titled “Hash 示例:”#!/usr/bin/env ruby
capitals = { "USA" => "Washington D.C.", "France" => "Paris", "Japan" => "Tokyo" }
capitals.each do |country, capital| puts "The capital of #{country} is #{capital}."end
# For hashes, each_pair is an alias for each.# You can also iterate over just keys or values:capitals.each_key { |country| puts "Country: #{country}" }capitals.each_value { |capital_city| puts "Capital: #{capital_city}" }这将产生:
The capital of USA is Washington D.C.The capital of France is Paris.The capital of Japan is Tokyo.Country: USACountry: FranceCountry: JapanCapital: Washington D.C.Capital: ParisCapital: Tokyomap(或 collect)迭代器:
Section titled “map(或 collect)迭代器:”map 迭代器(别名为 collect)用于转换集合。它迭代集合中的每个元素,执行块,并构建一个新数组,其中包含块对每个元素的返回值。
new_array = collection.map do |variable| # code whose return value will be part of the new arrayend
# Or for single-line blocks:new_array = collection.map { |variable| # expression }Array 示例:
Section titled “Array 示例:”#!/usr/bin/env ruby
original_numbers = [1, 2, 3, 4, 5]
# Create a new array with each number squaredsquared_numbers = original_numbers.map do |n| n * nendputs "Original numbers: #{original_numbers.inspect}"puts "Squared numbers: #{squared_numbers.inspect}"
# Using the alias 'collect'uppercased_fruits = ["apple", "banana", "cherry"].collect { |fruit| fruit.upcase }puts "Uppercased fruits: #{uppercased_fruits.inspect}"这将产生:
Original numbers: [1, 2, 3, 4, 5]Squared numbers: [1, 4, 9, 16, 25]Uppercased fruits: ["APPLE", "BANANA", "CHERRY"]注意:虽然 collect 是一个有效的别名,但在现代 Ruby 代码中通常首选使用 map 以保持清晰和一致性。
Hash 示例:
Section titled “Hash 示例:”当 map 用于 Hash 时,块会接收 [key, value] 对作为参数。它返回一个新数组。
#!/usr/bin/env ruby
scores = { "Alice" => 90, "Bob" => 75, "Charlie" => 82 }
descriptions = scores.map do |name, score| "#{name} scored #{score} points."endputs descriptions.inspect
# If you want to transform a hash into another hash, use `transform_values` (Ruby 2.4+) or `map` followed by `to_h`.# 如果想将哈希转换为另一个哈希,可以使用 `transform_values` (Ruby 2.4+) 或 `map` 后跟 `to_h`。incremented_scores = scores.transform_values { |score| score + 5 }puts "Incremented scores (Hash): #{incremented_scores.inspect}"
# Using map and to_h for more complex transformations resulting in a Hash# 使用 map 和 to_h 进行更复杂的转换以生成哈希student_data = scores.map do |name, score| [name.to_sym, { score: score, status: score >= 80 ? "Pass" : "Fail" }]end.to_hputs "Student data (Hash): #{student_data.inspect}"这将产生:
["Alice scored 90 points.", "Bob scored 75 points.", "Charlie scored 82 points."]Incremented scores (Hash): {"Alice"=>95, "Bob"=>80, "Charlie"=>87}Student data (Hash): {:Alice=>{:score=>90, :status=>"Pass"}, :Bob=>{:score=>75, :status=>"Fail"}, :Charlie=>{:score=>82, :status=>"Pass"}}Enumerable 模块中的其他有用迭代器:
Section titled “Enumerable 模块中的其他有用迭代器:”select(或find_all):返回一个新数组,其中包含块返回真值的所有元素。reject:与select相反。返回一个新数组,其中包含块返回假值或 nil 的所有元素。find(或detect):返回块返回真值的第一个元素。reduce(或inject):通过应用块或符号指定的二元操作来组合集合的所有元素。它非常强大,可用于求和、累积值等。any?、all?、none?:检查是否有任何、所有或没有元素满足块给出的条件。
#!/usr/bin/env ruby
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = numbers.select { |n| n.even? }puts "Even numbers: #{even_numbers.inspect}" #=> [2, 4, 6]
sum = numbers.reduce(0) { |accumulator, current_element| accumulator + current_element }# Alternative: numbers.reduce(:+) works for simple sums# 另一种方法:numbers.reduce(:+) 适用于简单的求和puts "Sum of numbers: #{sum}" #=> 21
puts "Are there any numbers > 5? #{numbers.any? { |n| n > 5 }}" #=> true迭代器在 Ruby 中随处可见。例如,处理用户输入、转换来自数据库或 API 的数据、过滤列表和生成报告。迭代器链允许优雅且可读的数据操作流程。
data = [{id: 1, name: "Alice", active: true}, {id: 2, name: "Bob", active: false}, {id: 3, name: "Charlie", active: true}]
# Get names of active users, uppercased# 获取活跃用户的姓名,并转换为大写active_user_names = data.select { |user| user[:active] } .map { |user| user[:name].upcase }
puts "Active user names: #{active_user_names.inspect}" #=> ["ALICE", "CHARLIE"]有关更多信息,请参阅 Ruby 文档中的 Enumerable 模块:https://ruby-doc.org/core/Enumerable.html