如何在Ruby中替换for循环?

9
在 Ruby 中使用 for 循环是不好的编程风格,这一点是广为人知的。一个给我推荐的编码风格指南(https://github.com/bbatsov/ruby-style-guide#source-code-layout)中指出:“除非你确切知道原因,否则从不使用 for 循环,大多数情况应该使用迭代器。for 循环是以 each 的形式实现的(因此它增加了一层间接性),但有一个扭曲之处——for 循环不引入新作用域(不像 each),在其块中定义的变量将在其外部可见。” 给出的示例是:
arr = [1, 2, 3]

#bad
for elem in arr do
  puts elem
end

# good
arr.each { |elem| puts elem }

我已经进行了研究,但找不到如何模拟 for 循环以提供可迭代的值,可以将其传递到其他地方或执行算术运算。

例如,我应该用什么替换:

for i in 0...size do
  puts array1[i]
  puts array2[size-1 - i]
  puts i % 2
end

如果只是一个数组很容易,但我经常需要当前位置来完成其他操作。要么有一个我没想到的简单解决方案,要么就需要使用for循环。此外,我听到人们谈论for好像它从来不需要使用。那么他们的解决方案是什么呢?

是否可以改进呢?如果有解决方案,请告诉我,谢谢。

2个回答

10
如果你想在迭代集合的同时跟踪索引,请使用 each_with_index
fields = ["name", "age", "height"]

fields.each_with_index do |field,i|
  puts "#{i}. #{field}" # 0. name, 1. age, 2. height
end

你的for i in 0...size的例子变成了:

array1.each_with_index do |item, i|
  puts item
  puts array2[size-1 - i]
  puts i % 2
end

假设array1array2具有相同的大小,最好将其写为array2[-1-i],以避免计算size - Borodin

3
不要忘记你也可以做像这样酷炫的事情。
fields = ["name", "age", "height"]

def output name, idx
  puts "#{idx}. #{name}"
end

fields.each_with_index &method(:output)

输出

0. name
1. age
2. height

您可以将这种技术用作类或实例方法。
class Printer
  def self.output data
    puts "raw: #{data}"
  end
end

class Kanon < Printer
  def initialize prefix
    @prefix = prefix
  end
  def output data
    puts "#{@prefix}: #{data}"
  end
end

def print printer, data
  # separating the block from `each` allows
  # you to do interesting things
  data.each &printer.method(:output)
end

使用类方法的示例
print Printer, ["a", "b", "c"]
# raw: a
# raw: b
# raw: c

例子使用实例方法
kanon = Kanon.new "kanon prints pretty"
print kanon, ["a", "b", "c"]
# kanon prints pretty: a
# kanon prints pretty: b
# kanon prints pretty: c

你可以这样做,但为什么要这样做呢?这真的有什么意义吗? - user229044
它将块与each*迭代分离。这意味着您可以将块放在任何地方;它可以是类或实例方法,也可以是动态proc等。只是展示了一些灵活性,因为OP似乎相对较新。已经获得+2,我认为我不是唯一一个发现这个有用的人。 - Mulan
我同意它很有用,但这并不意味着它相关或符合主题。在问题描述的情况下,这并不是有用的。 - user229044
演示如何从传统的for-in循环中分离块似乎与“如何在Ruby中替换for循环?”相关,但你是拥有56000多声望值的人,所以我想我不应该回答。 - Mulan
Meagar说的话和我想表达的一样——这不相关也不是主题。 - Plasmarob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接